@smoothbricks/lmao 0.2.2 → 0.2.3
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/dist/allocator.wasm +0 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/lib/JsBufferStrategy.d.ts +4 -3
- package/dist/lib/JsBufferStrategy.d.ts.map +1 -1
- package/dist/lib/JsBufferStrategy.js +18 -11
- package/dist/lib/arrow/lease.d.ts +10 -0
- package/dist/lib/arrow/lease.d.ts.map +1 -0
- package/dist/lib/arrow/lease.js +33 -0
- package/dist/lib/arrow/utils.d.ts +3 -4
- package/dist/lib/arrow/utils.d.ts.map +1 -1
- package/dist/lib/arrow/utils.js +12 -13
- package/dist/lib/arrow/vocabularyDictionary.d.ts +21 -0
- package/dist/lib/arrow/vocabularyDictionary.d.ts.map +1 -0
- package/dist/lib/arrow/vocabularyDictionary.js +95 -0
- package/dist/lib/bufferStrategy.d.ts +3 -2
- package/dist/lib/bufferStrategy.d.ts.map +1 -1
- package/dist/lib/cloudflare/traceRows.d.ts.map +1 -1
- package/dist/lib/cloudflare/traceRows.js +3 -2
- package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/evaluatorGenerator.js +12 -11
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +44 -82
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/fixedPositionWriterGenerator.js +223 -162
- package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts +63 -0
- package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts.map +1 -0
- package/dist/lib/codegen/spanLoggerClosureMaterializer.js +447 -0
- package/dist/lib/codegen/spanLoggerGenerator.d.ts +36 -19
- package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/spanLoggerGenerator.js +164 -158
- package/dist/lib/convertToArrow.d.ts +7 -2
- package/dist/lib/convertToArrow.d.ts.map +1 -1
- package/dist/lib/convertToArrow.js +499 -285
- package/dist/lib/defineOpContext.js +1 -1
- package/dist/lib/enumMetadata.d.ts +19 -0
- package/dist/lib/enumMetadata.d.ts.map +1 -0
- package/dist/lib/enumMetadata.js +86 -0
- package/dist/lib/flushScheduler.d.ts.map +1 -1
- package/dist/lib/flushScheduler.js +13 -4
- package/dist/lib/library.d.ts +16 -98
- package/dist/lib/library.d.ts.map +1 -1
- package/dist/lib/library.js +32 -525
- package/dist/lib/logBinding.d.ts +21 -27
- package/dist/lib/logBinding.d.ts.map +1 -1
- package/dist/lib/op.d.ts +30 -30
- package/dist/lib/op.d.ts.map +1 -1
- package/dist/lib/op.js +15 -22
- package/dist/lib/opContext/createOpGroup.d.ts +1 -1
- package/dist/lib/opContext/createOpGroup.d.ts.map +1 -1
- package/dist/lib/opContext/createOpGroup.js +22 -29
- package/dist/lib/opContext/defineOp.d.ts +4 -4
- package/dist/lib/opContext/defineOp.d.ts.map +1 -1
- package/dist/lib/opContext/defineOp.js +53 -10
- package/dist/lib/opContext/opGroupTypes.d.ts +2 -2
- package/dist/lib/opContext/opTypes.d.ts +1 -1
- package/dist/lib/opContext/opTypes.d.ts.map +1 -1
- package/dist/lib/opContext/spanContextTypes.d.ts +29 -14
- package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -1
- package/dist/lib/opContext/types.d.ts +4 -4
- package/dist/lib/opContext/types.d.ts.map +1 -1
- package/dist/lib/physicalLayoutPlan.d.ts +89 -0
- package/dist/lib/physicalLayoutPlan.d.ts.map +1 -0
- package/dist/lib/physicalLayoutPlan.js +442 -0
- package/dist/lib/resolveMessage.d.ts +9 -0
- package/dist/lib/resolveMessage.d.ts.map +1 -0
- package/dist/lib/resolveMessage.js +63 -0
- package/dist/lib/result.d.ts +5 -7
- package/dist/lib/result.d.ts.map +1 -1
- package/dist/lib/result.js +19 -26
- package/dist/lib/runtimeHint.d.ts +35 -0
- package/dist/lib/runtimeHint.d.ts.map +1 -0
- package/dist/lib/runtimeHint.js +79 -0
- package/dist/lib/schema/types.d.ts +1 -1
- package/dist/lib/schema/types.d.ts.map +1 -1
- package/dist/lib/span-buffer/aot/v1.d.ts +2 -0
- package/dist/lib/span-buffer/aot/v1.d.ts.map +1 -0
- package/dist/lib/span-buffer/aot/v1.js +24 -0
- package/dist/lib/spanBuffer.d.ts +33 -4
- package/dist/lib/spanBuffer.d.ts.map +1 -1
- package/dist/lib/spanBuffer.js +583 -91
- package/dist/lib/spanBufferStats.d.ts +1 -1
- package/dist/lib/spanBufferStats.d.ts.map +1 -1
- package/dist/lib/spanContext.d.ts +27 -51
- package/dist/lib/spanContext.d.ts.map +1 -1
- package/dist/lib/spanContext.js +822 -344
- package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -1
- package/dist/lib/sqlite/sqlite-common.js +20 -21
- package/dist/lib/testing/bun-harness.d.ts +8 -3
- package/dist/lib/testing/bun-harness.d.ts.map +1 -1
- package/dist/lib/testing/bun-harness.js +30 -18
- package/dist/lib/testing/extractFacts.d.ts +1 -1
- package/dist/lib/testing/extractFacts.d.ts.map +1 -1
- package/dist/lib/testing/extractFacts.js +55 -63
- package/dist/lib/testing/facts.d.ts +1 -1
- package/dist/lib/testing/facts.d.ts.map +1 -1
- package/dist/lib/testing/queryable-span.d.ts +1 -1
- package/dist/lib/testing/queryable-span.d.ts.map +1 -1
- package/dist/lib/testing/queryable-span.js +26 -28
- package/dist/lib/testing/span-query.d.ts.map +1 -1
- package/dist/lib/testing/span-query.js +19 -22
- package/dist/lib/testing/stdio-replay.d.ts.map +1 -1
- package/dist/lib/testing/stdio-replay.js +19 -8
- package/dist/lib/threadId.d.ts.map +1 -1
- package/dist/lib/threadId.js +6 -3
- package/dist/lib/traceRoot.d.ts +30 -8
- package/dist/lib/traceRoot.d.ts.map +1 -1
- package/dist/lib/traceRoot.es.d.ts +17 -15
- package/dist/lib/traceRoot.es.d.ts.map +1 -1
- package/dist/lib/traceRoot.es.js +68 -34
- package/dist/lib/traceRoot.js +11 -0
- package/dist/lib/traceRoot.node.d.ts +17 -19
- package/dist/lib/traceRoot.node.d.ts.map +1 -1
- package/dist/lib/traceRoot.node.js +66 -38
- package/dist/lib/traceTopology.d.ts +42 -0
- package/dist/lib/traceTopology.d.ts.map +1 -0
- package/dist/lib/traceTopology.js +260 -0
- package/dist/lib/tracer.d.ts +9 -5
- package/dist/lib/tracer.d.ts.map +1 -1
- package/dist/lib/tracer.js +65 -71
- package/dist/lib/tracers/ArrayQueueTracer.d.ts +1 -1
- package/dist/lib/tracers/ArrayQueueTracer.js +1 -1
- package/dist/lib/tracers/StdioTracer.d.ts.map +1 -1
- package/dist/lib/tracers/StdioTracer.js +15 -13
- package/dist/lib/tracers/TestTracer.d.ts +4 -6
- package/dist/lib/tracers/TestTracer.d.ts.map +1 -1
- package/dist/lib/tracers/TestTracer.js +6 -8
- package/dist/lib/types.d.ts +49 -32
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/vocabularyRegistry.d.ts +25 -0
- package/dist/lib/vocabularyRegistry.d.ts.map +1 -0
- package/dist/lib/vocabularyRegistry.js +372 -0
- package/dist/lib/wasm/WasmBufferStrategy.d.ts +6 -10
- package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -1
- package/dist/lib/wasm/WasmBufferStrategy.js +44 -37
- package/dist/lib/wasm/wasmAllocator.d.ts +27 -22
- package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -1
- package/dist/lib/wasm/wasmAllocator.js +66 -44
- package/dist/lib/wasm/wasmPhysicalLayout.d.ts +67 -0
- package/dist/lib/wasm/wasmPhysicalLayout.d.ts.map +1 -0
- package/dist/lib/wasm/wasmPhysicalLayout.js +179 -0
- package/dist/lib/wasm/wasmSpanBuffer.d.ts +79 -31
- package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -1
- package/dist/lib/wasm/wasmSpanBuffer.js +442 -272
- package/dist/lib/wasm/wasmTraceRoot.d.ts +24 -22
- package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -1
- package/dist/lib/wasm/wasmTraceRoot.js +110 -71
- package/dist/vocabulary/register/v1.d.ts +2 -0
- package/dist/vocabulary/register/v1.d.ts.map +1 -0
- package/dist/vocabulary/register/v1.js +1 -0
- package/dist/wasm.d.ts +5 -0
- package/dist/wasm.d.ts.map +1 -0
- package/dist/wasm.js +4 -0
- package/package.json +54 -6
- package/src/index.ts +1 -0
- package/src/lib/JsBufferStrategy.ts +27 -9
- package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +335 -37
- package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +97 -26
- package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +75 -15
- package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +30 -6
- package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +18 -21
- package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +5 -2
- package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +25 -7
- package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +3 -2
- package/src/lib/__tests__/buffer-overflow.test.ts +24 -18
- package/src/lib/__tests__/capability-span-context.test.ts +505 -0
- package/src/lib/__tests__/capacity-tuning.test.ts +5 -3
- package/src/lib/__tests__/eager-columns.test.ts +345 -0
- package/src/lib/__tests__/enum-metadata-aot.test.ts +153 -0
- package/src/lib/__tests__/enum-metadata.test.ts +177 -0
- package/src/lib/__tests__/fixtures/empty-vocabulary-runtime.fixture.ts +15 -0
- package/src/lib/__tests__/flushScheduler.test.ts +5 -1
- package/src/lib/__tests__/identity-view.property.test.ts +179 -0
- package/src/lib/__tests__/library.test.ts +19 -235
- package/src/lib/__tests__/message-buffer-families.test.ts +878 -0
- package/src/lib/__tests__/nested-library-tasks.test.ts +14 -15
- package/src/lib/__tests__/op-metadata.test.ts +1 -1
- package/src/lib/__tests__/op-type-safety.test.ts +5 -16
- package/src/lib/__tests__/physical-layout-plan.test.ts +333 -0
- package/src/lib/__tests__/remap-descriptor-integration.test.ts +381 -0
- package/src/lib/__tests__/root-context-construction.test.ts +414 -0
- package/src/lib/__tests__/span-auto-runtime.test.ts +386 -0
- package/src/lib/__tests__/span-buffer-segment-stats.test.ts +221 -0
- package/src/lib/__tests__/span-lifecycle.test.ts +53 -25
- package/src/lib/__tests__/spanbuffer-materializer-parity.test.ts +266 -0
- package/src/lib/__tests__/sync-async-trace.test.ts +24 -23
- package/src/lib/__tests__/tag-writer-aot.test.ts +214 -0
- package/src/lib/__tests__/test-helpers.ts +67 -12
- package/src/lib/__tests__/threadId.test.ts +62 -0
- package/src/lib/__tests__/timestamp.test.ts +221 -93
- package/src/lib/__tests__/traceTopology.property.test.ts +383 -0
- package/src/lib/__tests__/type-narrowing.test.ts +63 -0
- package/src/lib/__tests__/vocabulary-dense-decoding.test.ts +405 -0
- package/src/lib/__tests__/vocabularyRegistry.test.ts +313 -0
- package/src/lib/arrow/lease.ts +43 -0
- package/src/lib/arrow/utils.ts +10 -14
- package/src/lib/arrow/vocabularyDictionary.ts +123 -0
- package/src/lib/bufferStrategy.ts +9 -1
- package/src/lib/cloudflare/traceRows.ts +3 -2
- package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +21 -141
- package/src/lib/codegen/__tests__/fixedPositionWriter-parity.test.ts +273 -0
- package/src/lib/codegen/__tests__/fixedPositionWriter-uint64.test.ts +61 -34
- package/src/lib/codegen/__tests__/nullBitmap.test.ts +33 -37
- package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +34 -18
- package/src/lib/codegen/__tests__/spanLoggerMaterializerParity.test.ts +503 -0
- package/src/lib/codegen/evaluatorGenerator.ts +18 -13
- package/src/lib/codegen/fixedPositionWriterGenerator.ts +329 -245
- package/src/lib/codegen/spanLoggerClosureMaterializer.ts +598 -0
- package/src/lib/codegen/spanLoggerGenerator.ts +241 -177
- package/src/lib/convertToArrow.ts +598 -311
- package/src/lib/defineOpContext.ts +1 -1
- package/src/lib/enumMetadata.ts +121 -0
- package/src/lib/flushScheduler.ts +11 -5
- package/src/lib/library.ts +37 -595
- package/src/lib/logBinding.ts +21 -27
- package/src/lib/op.ts +75 -18
- package/src/lib/opContext/__tests__/retry.test.ts +27 -21
- package/src/lib/opContext/createOpGroup.ts +33 -31
- package/src/lib/opContext/defineOp.ts +88 -11
- package/src/lib/opContext/opGroupTypes.ts +2 -2
- package/src/lib/opContext/opTypes.ts +1 -1
- package/src/lib/opContext/spanContextTypes.ts +98 -17
- package/src/lib/opContext/types.ts +7 -3
- package/src/lib/physicalLayoutPlan.ts +598 -0
- package/src/lib/resolveMessage.ts +67 -0
- package/src/lib/result.ts +20 -33
- package/src/lib/runtimeHint.ts +98 -0
- package/src/lib/schema/__tests__/featureFlags.test.ts +2 -1
- package/src/lib/schema/builder.ts +1 -1
- package/src/lib/schema/types.ts +1 -1
- package/src/lib/span-buffer/aot/v1.ts +26 -0
- package/src/lib/spanBuffer.ts +658 -92
- package/src/lib/spanBufferStats.ts +1 -1
- package/src/lib/spanContext.ts +1350 -861
- package/src/lib/sqlite/sqlite-common.ts +20 -31
- package/src/lib/testing/__tests__/topology-traversal.test.ts +174 -0
- package/src/lib/testing/__tests__/vitest-harness.test.ts +2 -1
- package/src/lib/testing/bun-harness.ts +94 -43
- package/src/lib/testing/extractFacts.ts +64 -78
- package/src/lib/testing/facts.ts +1 -1
- package/src/lib/testing/queryable-span.ts +23 -30
- package/src/lib/testing/span-query.ts +16 -20
- package/src/lib/testing/stdio-replay.ts +25 -8
- package/src/lib/testing/vitest-harness.ts +1 -1
- package/src/lib/threadId.ts +6 -3
- package/src/lib/traceRoot.es.ts +77 -42
- package/src/lib/traceRoot.node.ts +75 -46
- package/src/lib/traceRoot.ts +41 -14
- package/src/lib/traceTopology.ts +279 -0
- package/src/lib/tracer.ts +109 -98
- package/src/lib/tracers/ArrayQueueTracer.ts +1 -1
- package/src/lib/tracers/StdioTracer.ts +15 -13
- package/src/lib/tracers/TestTracer.ts +6 -8
- package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +15 -10
- package/src/lib/tracers/__tests__/TestTracer.test.ts +23 -13
- package/src/lib/types.ts +64 -33
- package/src/lib/vocabularyRegistry.ts +439 -0
- package/src/lib/wasm/WasmBufferStrategy.ts +56 -48
- package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +215 -11
- package/src/lib/wasm/__tests__/allocatorFreeBlockClamp.test.ts +86 -0
- package/src/lib/wasm/__tests__/wasm-identity-view.test.ts +311 -0
- package/src/lib/wasm/__tests__/wasm-integration.test.ts +417 -44
- package/src/lib/wasm/__tests__/wasm-message-buffer-families.test.ts +588 -0
- package/src/lib/wasm/__tests__/wasmAllocator.test.ts +100 -668
- package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +419 -63
- package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +24 -29
- package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +2 -2
- package/src/lib/wasm/wasmAllocator.ts +131 -96
- package/src/lib/wasm/wasmPhysicalLayout.ts +309 -0
- package/src/lib/wasm/wasmSpanBuffer.ts +597 -341
- package/src/lib/wasm/wasmTraceRoot.ts +140 -78
- package/src/vocabulary/register/v1.ts +1 -0
- package/src/wasm.ts +19 -0
- package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +0 -319
- package/src/lib/__tests__/remapped-buffer-view.test.ts +0 -635
- package/src/lib/wasm/allocator.zig +0 -948
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import {
|
|
12
12
|
clearBitRange,
|
|
13
13
|
compareStrings,
|
|
14
|
+
countNulls,
|
|
14
15
|
createSortedDictionary,
|
|
15
16
|
DictionaryBuilder,
|
|
16
17
|
type FinalizedDictionary,
|
|
@@ -43,31 +44,47 @@ import { buildSortedCategoryDictionary, buildTextDictionary } from './arrow/dict
|
|
|
43
44
|
import {
|
|
44
45
|
type DictionaryColumnData,
|
|
45
46
|
type GenericColumnData,
|
|
46
|
-
getArrowIndexArrayConstructorOr,
|
|
47
|
-
getArrowIndexTypeOr,
|
|
48
47
|
makeArrowColumn,
|
|
49
48
|
type Utf8ColumnData,
|
|
50
49
|
} from './arrow/flechette.js';
|
|
50
|
+
import { type ArrowLease, createArrowLease } from './arrow/lease.js';
|
|
51
51
|
import {
|
|
52
52
|
calculateUtf8Offsets,
|
|
53
|
+
combineColumnChunks,
|
|
53
54
|
concatenateFloat64Arrays,
|
|
54
55
|
concatenateNullBitmaps,
|
|
55
56
|
concatenateUint8Arrays,
|
|
56
57
|
encodeUtf8Strings,
|
|
57
58
|
getArrowFieldName,
|
|
58
|
-
walkSpanTree,
|
|
59
59
|
} from './arrow/utils.js';
|
|
60
|
-
import {
|
|
61
|
-
|
|
60
|
+
import {
|
|
61
|
+
appendVocabularyDictionarySuffix,
|
|
62
|
+
getVocabularyDictionaryPrefix,
|
|
63
|
+
PREBUILT_ENTRY_TYPE_DICTIONARY,
|
|
64
|
+
} from './arrow/vocabularyDictionary.js';
|
|
65
|
+
import { type EnumLookupDescriptor, resolveEnumLookupDescriptor } from './enumMetadata.js';
|
|
66
|
+
import type { RemapDescriptor } from './logBinding.js';
|
|
67
|
+
import { resolveEntryType } from './resolveMessage.js';
|
|
68
|
+
import {
|
|
69
|
+
ENTRY_TYPE_ERROR,
|
|
70
|
+
ENTRY_TYPE_SPAN_START,
|
|
71
|
+
ENTRY_TYPE_TRACE,
|
|
72
|
+
SYSTEM_SCHEMA_FIELD_NAMES,
|
|
73
|
+
} from './schema/systemSchema.js';
|
|
74
|
+
import { getBinaryEncoder, getEnumUtf8, getSchemaType } from './schema/typeGuards.js';
|
|
62
75
|
import type { LogSchema } from './schema/types.js';
|
|
76
|
+
import { walkSpanTree } from './traceTopology.js';
|
|
63
77
|
import type { AnySpanBuffer, OpMetadata } from './types.js';
|
|
64
78
|
import { globalUtf8Cache } from './utf8Cache.js';
|
|
79
|
+
import type { VocabularyGeneration } from './vocabularyRegistry.js';
|
|
65
80
|
|
|
66
81
|
const DictBuilder = DictionaryBuilder;
|
|
67
82
|
const F64Array = Float64Array;
|
|
68
83
|
|
|
69
84
|
type BuiltArrowColumn = { column: Column<unknown>; nullCount: number };
|
|
70
85
|
type BuiltMetadataColumns = { fields: string[]; vectors: Column<unknown>[] };
|
|
86
|
+
type BuiltMessageColumn = { column: Column<unknown>; entryTypeIndices?: Int8Array };
|
|
87
|
+
type RemapsByBuffer = WeakMap<AnySpanBuffer, RemapDescriptor>;
|
|
71
88
|
|
|
72
89
|
export type SystemColumnBuilder = (
|
|
73
90
|
buffer: AnySpanBuffer,
|
|
@@ -173,16 +190,30 @@ function appendTables(base: Table, extra: Table): Table {
|
|
|
173
190
|
return tableFromColumns(columns);
|
|
174
191
|
}
|
|
175
192
|
|
|
176
|
-
function
|
|
177
|
-
|
|
193
|
+
function resolveColumnName(buffer: AnySpanBuffer, outputName: string, remaps: RemapsByBuffer): string {
|
|
194
|
+
return remaps.get(buffer)?.sourceNames[outputName] ?? outputName;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function getAllocatedStringColumn(
|
|
198
|
+
buffer: AnySpanBuffer,
|
|
199
|
+
columnName: string,
|
|
200
|
+
remaps?: RemapsByBuffer,
|
|
201
|
+
): string[] | undefined {
|
|
202
|
+
const sourceName = remaps ? resolveColumnName(buffer, columnName, remaps) : columnName;
|
|
203
|
+
const column = buffer.getColumnIfAllocated(sourceName);
|
|
178
204
|
if (!Array.isArray(column)) {
|
|
179
205
|
return undefined;
|
|
180
206
|
}
|
|
181
207
|
return isStringArray(column) ? column : undefined;
|
|
182
208
|
}
|
|
183
209
|
|
|
184
|
-
function getAllocatedBinaryColumn(
|
|
185
|
-
|
|
210
|
+
function getAllocatedBinaryColumn(
|
|
211
|
+
buffer: AnySpanBuffer,
|
|
212
|
+
columnName: string,
|
|
213
|
+
remaps?: RemapsByBuffer,
|
|
214
|
+
): unknown[] | undefined {
|
|
215
|
+
const sourceName = remaps ? resolveColumnName(buffer, columnName, remaps) : columnName;
|
|
216
|
+
const column = buffer.getColumnIfAllocated(sourceName);
|
|
186
217
|
return Array.isArray(column) ? column : undefined;
|
|
187
218
|
}
|
|
188
219
|
|
|
@@ -191,18 +222,21 @@ function getAllocatedBinaryColumn(buffer: AnySpanBuffer, columnName: string): un
|
|
|
191
222
|
// Arrow conversion. These typed readers pull from the buffer's immutable _scopeValues; the
|
|
192
223
|
// per-column fill loops below call them so a row with a direct write keeps its value and scope
|
|
193
224
|
// only fills the gaps.
|
|
194
|
-
function getStringScopeValue(buffer: AnySpanBuffer, fieldName: string): string | undefined {
|
|
195
|
-
const
|
|
225
|
+
function getStringScopeValue(buffer: AnySpanBuffer, fieldName: string, remaps?: RemapsByBuffer): string | undefined {
|
|
226
|
+
const sourceName = remaps ? resolveColumnName(buffer, fieldName, remaps) : fieldName;
|
|
227
|
+
const value = buffer._scopeValues?.[sourceName];
|
|
196
228
|
return typeof value === 'string' ? value : undefined;
|
|
197
229
|
}
|
|
198
230
|
|
|
199
|
-
function getNumberScopeValue(buffer: AnySpanBuffer, fieldName: string): number | undefined {
|
|
200
|
-
const
|
|
231
|
+
function getNumberScopeValue(buffer: AnySpanBuffer, fieldName: string, remaps?: RemapsByBuffer): number | undefined {
|
|
232
|
+
const sourceName = remaps ? resolveColumnName(buffer, fieldName, remaps) : fieldName;
|
|
233
|
+
const value = buffer._scopeValues?.[sourceName];
|
|
201
234
|
return typeof value === 'number' ? value : undefined;
|
|
202
235
|
}
|
|
203
236
|
|
|
204
|
-
function getBooleanScopeValue(buffer: AnySpanBuffer, fieldName: string): boolean | undefined {
|
|
205
|
-
const
|
|
237
|
+
function getBooleanScopeValue(buffer: AnySpanBuffer, fieldName: string, remaps?: RemapsByBuffer): boolean | undefined {
|
|
238
|
+
const sourceName = remaps ? resolveColumnName(buffer, fieldName, remaps) : fieldName;
|
|
239
|
+
const value = buffer._scopeValues?.[sourceName];
|
|
206
240
|
return typeof value === 'boolean' ? value : undefined;
|
|
207
241
|
}
|
|
208
242
|
//#endregion smoo/lmao!n/scope-attributes.arrow-fill
|
|
@@ -219,11 +253,179 @@ function isStringArray(value: unknown): value is string[] {
|
|
|
219
253
|
}
|
|
220
254
|
|
|
221
255
|
function indexTypeForCount(count: number): IntType {
|
|
222
|
-
if (count <=
|
|
223
|
-
if (count <=
|
|
256
|
+
if (count <= 0x100) return uint8();
|
|
257
|
+
if (count <= 0x1_0000) return uint16();
|
|
224
258
|
return uint32();
|
|
225
259
|
}
|
|
226
260
|
|
|
261
|
+
function assertStaticMessageKind(buffer: AnySpanBuffer, row: number, entryType: number, denseIndex: number): void {
|
|
262
|
+
const generation = buffer._vocabularyGeneration;
|
|
263
|
+
if (denseIndex >= generation.ids.length) {
|
|
264
|
+
throw new Error(`Invalid vocabulary dense index ${denseIndex} for generation ${generation.generation}`);
|
|
265
|
+
}
|
|
266
|
+
const expectedKind =
|
|
267
|
+
entryType === ENTRY_TYPE_SPAN_START ? 2 : entryType >= ENTRY_TYPE_TRACE && entryType <= ENTRY_TYPE_ERROR ? 1 : 0;
|
|
268
|
+
if (expectedKind === 0) {
|
|
269
|
+
throw new Error(`Entry type ${entryType} at row ${row} cannot carry a static vocabulary identity`);
|
|
270
|
+
}
|
|
271
|
+
const actualKind = generation.kindTags[denseIndex];
|
|
272
|
+
if (actualKind !== expectedKind) {
|
|
273
|
+
throw new Error(
|
|
274
|
+
`Vocabulary kind ${actualKind} at dense index ${denseIndex} does not match entry type ${entryType} at row ${row}`,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function buildMessageColumn(
|
|
280
|
+
buffers: AnySpanBuffer[],
|
|
281
|
+
totalRows: number,
|
|
282
|
+
dictionaryId?: number,
|
|
283
|
+
materializeEntryTypes = true,
|
|
284
|
+
): BuiltMessageColumn {
|
|
285
|
+
let generation = buffers[0]._vocabularyGeneration;
|
|
286
|
+
for (let index = 1; index < buffers.length; index++) {
|
|
287
|
+
const candidate = buffers[index]._vocabularyGeneration;
|
|
288
|
+
if (candidate.generation > generation.generation) generation = candidate;
|
|
289
|
+
}
|
|
290
|
+
const prefix = getVocabularyDictionaryPrefix(generation);
|
|
291
|
+
const indices = new Uint32Array(totalRows);
|
|
292
|
+
const entryTypeIndices = materializeEntryTypes ? new Int8Array(totalRows) : undefined;
|
|
293
|
+
const nullBitmap = new Uint8Array(Math.ceil(totalRows / 8));
|
|
294
|
+
let nullCount = 0;
|
|
295
|
+
let rowOffset = 0;
|
|
296
|
+
let suffixValues: string[] | undefined;
|
|
297
|
+
let suffixIndices: Map<string, number> | undefined;
|
|
298
|
+
|
|
299
|
+
for (const buffer of buffers) {
|
|
300
|
+
const plannedStorage = buffer._opMetadata._physicalLayoutPlan?.arrowExposure.messageIdentityStorage;
|
|
301
|
+
const messageIdentityStorage =
|
|
302
|
+
plannedStorage ??
|
|
303
|
+
(buffer._messagePhysicalLayout === 'current'
|
|
304
|
+
? 'local-u16'
|
|
305
|
+
: buffer._messagePhysicalLayout === 'specialized'
|
|
306
|
+
? 'global-u32'
|
|
307
|
+
: 'packed-row-headers');
|
|
308
|
+
for (let row = 0; row < buffer._writeIndex; row++) {
|
|
309
|
+
const outputRow = rowOffset + row;
|
|
310
|
+
const hasDedicatedMessage =
|
|
311
|
+
(row === 0 && buffer._spanName !== undefined) || (row === 1 && buffer._terminalMessage !== undefined);
|
|
312
|
+
let dictionaryIndex: number | undefined;
|
|
313
|
+
let entryType: number;
|
|
314
|
+
|
|
315
|
+
if (messageIdentityStorage === 'local-u16') {
|
|
316
|
+
entryType = resolveEntryType(buffer, row);
|
|
317
|
+
const localId = buffer._messageIds?.[row];
|
|
318
|
+
const rawMessage = buffer.message_values?.[row];
|
|
319
|
+
if (row === 0 && typeof buffer._spanName === 'number') {
|
|
320
|
+
if ((localId !== undefined && localId > 0) || rawMessage !== undefined) {
|
|
321
|
+
throw new Error(`Local row ${row} has conflicting static message identities`);
|
|
322
|
+
}
|
|
323
|
+
dictionaryIndex = buffer._spanName;
|
|
324
|
+
} else if (localId !== undefined && localId > 0) {
|
|
325
|
+
if (hasDedicatedMessage || rawMessage !== undefined) {
|
|
326
|
+
throw new Error(`Local row ${row} has conflicting static and raw message storage`);
|
|
327
|
+
}
|
|
328
|
+
dictionaryIndex = buffer._opMetadata._physicalLayoutPlan?.localMessageDictionary[localId - 1];
|
|
329
|
+
if (dictionaryIndex === undefined) throw new Error(`Missing local message dictionary entry ${localId}`);
|
|
330
|
+
}
|
|
331
|
+
} else if (messageIdentityStorage === 'global-u32') {
|
|
332
|
+
entryType = resolveEntryType(buffer, row);
|
|
333
|
+
const encodedDenseIndex = buffer._logHeaders?.[row];
|
|
334
|
+
if (encodedDenseIndex !== undefined && encodedDenseIndex > 0) {
|
|
335
|
+
if (hasDedicatedMessage || buffer.message_values?.[row] !== undefined) {
|
|
336
|
+
throw new Error(`Global row ${row} has conflicting static and raw message storage`);
|
|
337
|
+
}
|
|
338
|
+
dictionaryIndex = encodedDenseIndex - 1;
|
|
339
|
+
}
|
|
340
|
+
} else {
|
|
341
|
+
const rowHeaders = buffer._rowHeaders;
|
|
342
|
+
if (rowHeaders === undefined) throw new TypeError('Packed message layout is missing row headers');
|
|
343
|
+
const header = rowHeaders[row];
|
|
344
|
+
entryType = header & 0xff;
|
|
345
|
+
const encodedDenseIndex = header >>> 8;
|
|
346
|
+
if (encodedDenseIndex !== 0) {
|
|
347
|
+
if (hasDedicatedMessage) {
|
|
348
|
+
throw new Error(`Packed row ${row} has conflicting static and dedicated message storage`);
|
|
349
|
+
}
|
|
350
|
+
dictionaryIndex = encodedDenseIndex - 1;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
const dedicatedDenseIndex = row === 0 && typeof buffer._spanName === 'number' ? buffer._spanName : undefined;
|
|
354
|
+
if (dedicatedDenseIndex !== undefined) {
|
|
355
|
+
if (buffer.message_values?.[row] !== undefined) {
|
|
356
|
+
throw new Error(`Row ${row} has conflicting dedicated static and raw message storage`);
|
|
357
|
+
}
|
|
358
|
+
dictionaryIndex ??= dedicatedDenseIndex;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (entryTypeIndices !== undefined) entryTypeIndices[outputRow] = entryType;
|
|
362
|
+
if (dictionaryIndex !== undefined) {
|
|
363
|
+
assertStaticMessageKind(buffer, row, entryType, dictionaryIndex);
|
|
364
|
+
} else {
|
|
365
|
+
const message =
|
|
366
|
+
row === 0 && typeof buffer._spanName === 'string'
|
|
367
|
+
? buffer._spanName
|
|
368
|
+
: row === 1 && buffer._terminalMessage !== undefined
|
|
369
|
+
? buffer._terminalMessage
|
|
370
|
+
: buffer.message_values?.[row];
|
|
371
|
+
if (message === undefined) {
|
|
372
|
+
nullCount++;
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
const staticIndex = prefix.valueToDenseIndex.get(message);
|
|
376
|
+
if (staticIndex !== undefined) {
|
|
377
|
+
dictionaryIndex = staticIndex;
|
|
378
|
+
} else {
|
|
379
|
+
let dynamicIndex = suffixIndices?.get(message);
|
|
380
|
+
if (dynamicIndex === undefined) {
|
|
381
|
+
suffixValues ??= [];
|
|
382
|
+
suffixIndices ??= new Map<string, number>();
|
|
383
|
+
dynamicIndex = suffixValues.length;
|
|
384
|
+
suffixValues.push(message);
|
|
385
|
+
suffixIndices.set(message, dynamicIndex);
|
|
386
|
+
}
|
|
387
|
+
dictionaryIndex = prefix.length + dynamicIndex;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
indices[outputRow] = dictionaryIndex;
|
|
391
|
+
nullBitmap[outputRow >>> 3] |= 1 << (outputRow & 7);
|
|
392
|
+
}
|
|
393
|
+
rowOffset += buffer._writeIndex;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
let messageDictionary = prefix.column;
|
|
397
|
+
if (suffixValues !== undefined) {
|
|
398
|
+
const encoded = globalUtf8Cache.encodeMany(suffixValues);
|
|
399
|
+
const suffix = buildColumn(
|
|
400
|
+
buildData({
|
|
401
|
+
type: utf8(),
|
|
402
|
+
offset: 0,
|
|
403
|
+
length: suffixValues.length,
|
|
404
|
+
nullCount: 0,
|
|
405
|
+
valueOffsets: encoded.offsets,
|
|
406
|
+
data: encoded.data,
|
|
407
|
+
}),
|
|
408
|
+
);
|
|
409
|
+
messageDictionary = appendVocabularyDictionarySuffix(prefix, suffix, suffixValues);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return {
|
|
413
|
+
column: buildColumn(
|
|
414
|
+
buildData({
|
|
415
|
+
type:
|
|
416
|
+
dictionaryId === undefined ? dictionary(utf8(), uint32()) : dictionary(utf8(), uint32(), false, dictionaryId),
|
|
417
|
+
offset: 0,
|
|
418
|
+
length: totalRows,
|
|
419
|
+
nullCount,
|
|
420
|
+
data: indices,
|
|
421
|
+
nullBitmap: nullCount > 0 ? nullBitmap : undefined,
|
|
422
|
+
dictionary: messageDictionary,
|
|
423
|
+
}),
|
|
424
|
+
),
|
|
425
|
+
entryTypeIndices,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
227
429
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
228
430
|
// Shared metadata column helpers (used by both buildMetadataColumnsWithFields
|
|
229
431
|
// and convertBuffersWithSharedDicts to avoid duplication)
|
|
@@ -321,75 +523,100 @@ function buildNonDictIdentityColumns(
|
|
|
321
523
|
);
|
|
322
524
|
}
|
|
323
525
|
|
|
324
|
-
/**
|
|
325
|
-
* Build timestamp column from buffers.
|
|
326
|
-
*/
|
|
327
526
|
function buildTimestampColumn(
|
|
328
527
|
buffers: AnySpanBuffer[],
|
|
329
528
|
totalRows: number,
|
|
330
529
|
fields: string[],
|
|
331
530
|
vectors: Column<unknown>[],
|
|
531
|
+
borrowChunks = false,
|
|
332
532
|
): void {
|
|
533
|
+
const timestampType = timestamp(TimeUnit.NANOSECOND);
|
|
534
|
+
fields.push('timestamp');
|
|
535
|
+
if (borrowChunks) {
|
|
536
|
+
const chunks = buffers.map((buffer) =>
|
|
537
|
+
buildColumn(
|
|
538
|
+
buildData({
|
|
539
|
+
type: timestampType,
|
|
540
|
+
offset: 0,
|
|
541
|
+
length: buffer._writeIndex,
|
|
542
|
+
nullCount: 0,
|
|
543
|
+
data: buffer.timestamp.subarray(0, buffer._writeIndex),
|
|
544
|
+
}),
|
|
545
|
+
),
|
|
546
|
+
);
|
|
547
|
+
vectors.push(combineColumnChunks(chunks));
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
333
550
|
const allTimestamps = new BigInt64Array(totalRows);
|
|
334
551
|
let offset = 0;
|
|
335
|
-
for (const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
allTimestamps.set(buf.timestamp.subarray(0, buf._writeIndex), offset);
|
|
340
|
-
offset += buf._writeIndex;
|
|
552
|
+
for (const buffer of buffers) {
|
|
553
|
+
allTimestamps.set(buffer.timestamp.subarray(0, buffer._writeIndex), offset);
|
|
554
|
+
offset += buffer._writeIndex;
|
|
341
555
|
}
|
|
342
|
-
fields.push('timestamp');
|
|
343
556
|
vectors.push(
|
|
344
|
-
buildColumn(
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
557
|
+
buildColumn(buildData({ type: timestampType, offset: 0, length: totalRows, nullCount: 0, data: allTimestamps })),
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
function canBorrowEntryTypeChunks(buffers: AnySpanBuffer[], borrowChunks: boolean): boolean {
|
|
562
|
+
return (
|
|
563
|
+
borrowChunks &&
|
|
564
|
+
buffers.every((buffer) => {
|
|
565
|
+
const declared = buffer._opMetadata._physicalLayoutPlan?.arrowExposure.entryTypeStorage;
|
|
566
|
+
return declared === 'borrowed-u8' || (declared === undefined && buffer.entry_type !== undefined);
|
|
567
|
+
})
|
|
353
568
|
);
|
|
354
569
|
}
|
|
355
570
|
|
|
356
|
-
/**
|
|
357
|
-
* Build entry_type dictionary column.
|
|
358
|
-
*/
|
|
359
571
|
function buildEntryTypeColumn(
|
|
360
572
|
buffers: AnySpanBuffer[],
|
|
361
573
|
totalRows: number,
|
|
362
574
|
fields: string[],
|
|
363
575
|
vectors: Column<unknown>[],
|
|
364
576
|
dictType?: ReturnType<typeof dictionary>,
|
|
577
|
+
borrowChunks = false,
|
|
578
|
+
classifiedEntryTypes?: Int8Array,
|
|
365
579
|
): void {
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
580
|
+
const entryTypeDictionary = PREBUILT_ENTRY_TYPE_DICTIONARY;
|
|
581
|
+
const type = dictType ?? dictionary(utf8(), int8());
|
|
582
|
+
fields.push('entry_type');
|
|
583
|
+
if (canBorrowEntryTypeChunks(buffers, borrowChunks)) {
|
|
584
|
+
const chunks = buffers.map((buffer) => {
|
|
585
|
+
const source = buffer.entry_type;
|
|
586
|
+
if (source === undefined) throw new TypeError('Current/specialized buffer is missing entry types');
|
|
587
|
+
const values = new Int8Array(source.buffer, source.byteOffset, buffer._writeIndex);
|
|
588
|
+
return buildColumn(
|
|
589
|
+
buildData({
|
|
590
|
+
type,
|
|
591
|
+
offset: 0,
|
|
592
|
+
length: buffer._writeIndex,
|
|
593
|
+
nullCount: 0,
|
|
594
|
+
data: values,
|
|
595
|
+
dictionary: entryTypeDictionary,
|
|
596
|
+
}),
|
|
597
|
+
);
|
|
598
|
+
});
|
|
599
|
+
vectors.push(combineColumnChunks(chunks));
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
const entryTypeIndices = classifiedEntryTypes ?? new Int8Array(totalRows);
|
|
603
|
+
if (classifiedEntryTypes === undefined) {
|
|
604
|
+
let offset = 0;
|
|
605
|
+
for (const buffer of buffers) {
|
|
606
|
+
for (let row = 0; row < buffer._writeIndex; row++) {
|
|
607
|
+
entryTypeIndices[offset++] = resolveEntryType(buffer, row);
|
|
608
|
+
}
|
|
371
609
|
}
|
|
372
|
-
entryTypeIndices.set(buf.entry_type.subarray(0, buf._writeIndex), offset);
|
|
373
|
-
offset += buf._writeIndex;
|
|
374
610
|
}
|
|
375
|
-
const entryTypeDictData = buildData({
|
|
376
|
-
type: utf8(),
|
|
377
|
-
offset: 0,
|
|
378
|
-
length: ENTRY_TYPE_NAMES.length,
|
|
379
|
-
nullCount: 0,
|
|
380
|
-
valueOffsets: calculateUtf8Offsets(ENTRY_TYPE_NAMES),
|
|
381
|
-
data: encodeUtf8Strings(ENTRY_TYPE_NAMES),
|
|
382
|
-
});
|
|
383
|
-
fields.push('entry_type');
|
|
384
611
|
vectors.push(
|
|
385
612
|
buildColumn(
|
|
386
613
|
buildData({
|
|
387
|
-
type
|
|
614
|
+
type,
|
|
388
615
|
offset: 0,
|
|
389
616
|
length: totalRows,
|
|
390
617
|
nullCount: 0,
|
|
391
618
|
data: entryTypeIndices,
|
|
392
|
-
dictionary:
|
|
619
|
+
dictionary: entryTypeDictionary,
|
|
393
620
|
}),
|
|
394
621
|
),
|
|
395
622
|
);
|
|
@@ -462,14 +689,16 @@ function buildBinaryColumnFromBuffers(
|
|
|
462
689
|
columnName: string,
|
|
463
690
|
totalRows: number,
|
|
464
691
|
fieldSchema: unknown,
|
|
692
|
+
remaps?: RemapsByBuffer,
|
|
465
693
|
): BuiltArrowColumn {
|
|
466
694
|
const encoder = getBinaryEncoder(fieldSchema);
|
|
467
695
|
|
|
468
696
|
// Collect all values from buffers, encode each if encoder is present
|
|
469
697
|
const allValues: (Uint8Array | null)[] = [];
|
|
470
698
|
for (const buf of buffers) {
|
|
471
|
-
const col = getAllocatedBinaryColumn(buf, columnName);
|
|
472
|
-
const
|
|
699
|
+
const col = getAllocatedBinaryColumn(buf, columnName, remaps);
|
|
700
|
+
const sourceName = remaps ? resolveColumnName(buf, columnName, remaps) : columnName;
|
|
701
|
+
const srcNulls = buf.getNullsIfAllocated(sourceName);
|
|
473
702
|
for (let i = 0; i < buf._writeIndex; i++) {
|
|
474
703
|
if (srcNulls) {
|
|
475
704
|
const isValid = (srcNulls[i >>> 3] & (1 << (i & 7))) !== 0;
|
|
@@ -549,16 +778,18 @@ function buildBinaryColumnFromBuffers(
|
|
|
549
778
|
* Dictionaries are built from the data in this batch only and are not shared
|
|
550
779
|
* with other batches, even when combined into a Table.
|
|
551
780
|
*/
|
|
552
|
-
export function convertToTable(
|
|
781
|
+
export function convertToTable(
|
|
782
|
+
buffer: AnySpanBuffer,
|
|
783
|
+
systemColumnBuilder?: SystemColumnBuilder,
|
|
784
|
+
borrowChunks = false,
|
|
785
|
+
): Table {
|
|
553
786
|
const buffers: AnySpanBuffer[] = [];
|
|
554
787
|
let currentBuffer: AnySpanBuffer | undefined = buffer;
|
|
555
|
-
|
|
556
788
|
while (currentBuffer) {
|
|
557
789
|
buffers.push(currentBuffer);
|
|
558
790
|
currentBuffer = currentBuffer._overflow;
|
|
559
791
|
}
|
|
560
|
-
|
|
561
|
-
return convertBuffersToTable(buffers, systemColumnBuilder);
|
|
792
|
+
return convertBuffersToTable(buffers, systemColumnBuilder, borrowChunks);
|
|
562
793
|
}
|
|
563
794
|
|
|
564
795
|
/**
|
|
@@ -568,13 +799,18 @@ export function convertToTable(buffer: AnySpanBuffer, systemColumnBuilder?: Syst
|
|
|
568
799
|
* Dictionaries are built from the data in this batch only and are not shared
|
|
569
800
|
* with other batches, even when combined into a Table.
|
|
570
801
|
*/
|
|
571
|
-
function convertBuffersToTable(
|
|
802
|
+
function convertBuffersToTable(
|
|
803
|
+
buffers: AnySpanBuffer[],
|
|
804
|
+
systemColumnBuilder?: SystemColumnBuilder,
|
|
805
|
+
borrowChunks = false,
|
|
806
|
+
): Table {
|
|
572
807
|
if (buffers.length === 0) return tableFromColumns({});
|
|
573
808
|
|
|
574
809
|
const totalRows = buffers.reduce((sum, buf) => sum + buf._writeIndex, 0);
|
|
575
810
|
if (totalRows === 0) return tableFromColumns({});
|
|
576
811
|
|
|
577
812
|
const schema: LogSchema = buffers[0]._logSchema;
|
|
813
|
+
const enumLookup = resolveEnumLookupDescriptor(schema);
|
|
578
814
|
|
|
579
815
|
// Build vectors first, then derive schema from them
|
|
580
816
|
// This ensures Field types and vector data types are identical (Arrow IPC requirement)
|
|
@@ -586,57 +822,22 @@ function convertBuffersToTable(buffers: AnySpanBuffer[], systemColumnBuilder?: S
|
|
|
586
822
|
fields.push(...systemColumns.fields);
|
|
587
823
|
vectors.push(...systemColumns.vectors);
|
|
588
824
|
} else {
|
|
589
|
-
|
|
590
|
-
const
|
|
825
|
+
const borrowEntryTypes = canBorrowEntryTypeChunks(buffers, borrowChunks);
|
|
826
|
+
const messageResult = buildMessageColumn(buffers, totalRows, undefined, !borrowEntryTypes);
|
|
827
|
+
// Build metadata columns - returns both fields and vectors with matching types.
|
|
828
|
+
const metadataResult = buildMetadataColumnsWithFields(
|
|
829
|
+
buffers,
|
|
830
|
+
totalRows,
|
|
831
|
+
borrowChunks,
|
|
832
|
+
messageResult.entryTypeIndices,
|
|
833
|
+
);
|
|
591
834
|
fields.push(...metadataResult.fields);
|
|
592
835
|
vectors.push(...metadataResult.vectors);
|
|
593
836
|
|
|
594
|
-
//
|
|
595
|
-
|
|
596
|
-
let {
|
|
597
|
-
dictionary: dictValues,
|
|
598
|
-
indices,
|
|
599
|
-
arrowIndexType,
|
|
600
|
-
nullBitmap,
|
|
601
|
-
} = buildSortedCategoryDictionary(buffers, 'message', maskTransform);
|
|
602
|
-
// Ensure dictionary has at least one entry (empty string) if no messages were written
|
|
603
|
-
if (dictValues.length === 0) {
|
|
604
|
-
dictValues = [''];
|
|
605
|
-
}
|
|
606
|
-
// Ensure nullBitmap is all 1s (all valid) for eager column
|
|
607
|
-
if (!nullBitmap) {
|
|
608
|
-
const bitmapBytes = Math.ceil(totalRows / 8);
|
|
609
|
-
nullBitmap = new Uint8Array(bitmapBytes);
|
|
610
|
-
nullBitmap.fill(0xff);
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// CRITICAL: Create ONE Dictionary type instance for field and batch data
|
|
614
|
-
// Arrow Schema validates that fields with same dictionary ID have identical type references
|
|
615
|
-
const messageDictType = dictionary(utf8(), arrowIndexType);
|
|
837
|
+
// Static vocabulary values form an immutable prefix. Only raw messages
|
|
838
|
+
// missing from that prefix are interned into a first-seen suffix.
|
|
616
839
|
fields.push('message');
|
|
617
|
-
|
|
618
|
-
const { data: messageUtf8Data, offsets: messageUtf8Offsets } = globalUtf8Cache.encodeMany(dictValues);
|
|
619
|
-
|
|
620
|
-
const messageDictData = buildData({
|
|
621
|
-
type: utf8(),
|
|
622
|
-
offset: 0,
|
|
623
|
-
length: dictValues.length,
|
|
624
|
-
nullCount: 0,
|
|
625
|
-
valueOffsets: messageUtf8Offsets,
|
|
626
|
-
data: messageUtf8Data,
|
|
627
|
-
});
|
|
628
|
-
|
|
629
|
-
const messageData = buildData({
|
|
630
|
-
type: messageDictType,
|
|
631
|
-
offset: 0,
|
|
632
|
-
length: totalRows,
|
|
633
|
-
nullCount: 0, // message is eager, never null
|
|
634
|
-
data: indices,
|
|
635
|
-
nullBitmap, // Always include nullBitmap for message (even though nullCount is 0)
|
|
636
|
-
dictionary: buildColumn(messageDictData),
|
|
637
|
-
});
|
|
638
|
-
|
|
639
|
-
vectors.push(buildColumn(messageData));
|
|
840
|
+
vectors.push(messageResult.column);
|
|
640
841
|
}
|
|
641
842
|
|
|
642
843
|
// Build user attribute vectors
|
|
@@ -649,17 +850,18 @@ function convertBuffersToTable(buffers: AnySpanBuffer[], systemColumnBuilder?: S
|
|
|
649
850
|
const columnName = fieldName; // User columns have no prefix
|
|
650
851
|
|
|
651
852
|
if (lmaoType === 'enum') {
|
|
652
|
-
const
|
|
853
|
+
const descriptor = enumLookup.byField[fieldName];
|
|
854
|
+
if (!descriptor) throw new TypeError(`Enum lookup missing for field '${fieldName}'`);
|
|
855
|
+
const enumValues = descriptor.values;
|
|
653
856
|
const enumUtf8 = getEnumUtf8(fieldSchema);
|
|
654
|
-
|
|
655
|
-
const
|
|
656
|
-
const arrowIndexType = getArrowIndexTypeOr(fieldSchema, uint8());
|
|
857
|
+
const indexArrayCtor = descriptor.indexArrayConstructor;
|
|
858
|
+
const arrowIndexType = indexTypeForCount(enumValues.length);
|
|
657
859
|
// Collect value arrays - need to handle different TypedArray types
|
|
658
860
|
const valueArrays: (Uint8Array | Uint16Array | Uint32Array)[] = [];
|
|
659
861
|
for (const buf of buffers) {
|
|
660
862
|
const column = buf.getColumnIfAllocated(columnName);
|
|
661
863
|
if (column && column instanceof indexArrayCtor) {
|
|
662
|
-
valueArrays.push(column.subarray(0, buf._writeIndex));
|
|
864
|
+
valueArrays.push(column.subarray(0, buf._writeIndex).slice());
|
|
663
865
|
} else {
|
|
664
866
|
valueArrays.push(new indexArrayCtor(buf._writeIndex));
|
|
665
867
|
}
|
|
@@ -784,33 +986,52 @@ function convertBuffersToTable(buffers: AnySpanBuffer[], systemColumnBuilder?: S
|
|
|
784
986
|
vectors.push(buildColumn(textData));
|
|
785
987
|
}
|
|
786
988
|
} else if (lmaoType === 'number') {
|
|
787
|
-
const valueArrays: Float64Array[] = [];
|
|
788
|
-
|
|
789
|
-
for (const buf of buffers) {
|
|
790
|
-
const column = buf.getColumnIfAllocated(columnName);
|
|
791
|
-
if (column && column instanceof Float64Array) {
|
|
792
|
-
valueArrays.push(column.subarray(0, buf._writeIndex));
|
|
793
|
-
} else {
|
|
794
|
-
valueArrays.push(new F64Array(buf._writeIndex));
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
const allValues = concatenateFloat64Arrays(valueArrays);
|
|
799
|
-
const { nullBitmap, nullCount } = concatenateNullBitmaps(buffers, columnName);
|
|
800
|
-
|
|
801
989
|
const numberType = float64();
|
|
802
990
|
fields.push(arrowFieldName);
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
991
|
+
const borrowed = borrowChunks
|
|
992
|
+
? buffers.map((buffer) => {
|
|
993
|
+
const column = buffer.getColumnIfAllocated(columnName);
|
|
994
|
+
const validity = buffer.getNullsIfAllocated(columnName);
|
|
995
|
+
if (!(column instanceof Float64Array) || !(validity instanceof Uint8Array)) return undefined;
|
|
996
|
+
return buildColumn(
|
|
997
|
+
buildData({
|
|
998
|
+
type: numberType,
|
|
999
|
+
offset: 0,
|
|
1000
|
+
length: buffer._writeIndex,
|
|
1001
|
+
nullCount: countNulls(validity, buffer._writeIndex),
|
|
1002
|
+
data: column.subarray(0, buffer._writeIndex),
|
|
1003
|
+
nullBitmap: validity.subarray(0, Math.ceil(buffer._writeIndex / 8)),
|
|
1004
|
+
}),
|
|
1005
|
+
);
|
|
1006
|
+
})
|
|
1007
|
+
: undefined;
|
|
1008
|
+
if (borrowed?.every((chunk): chunk is Column<unknown> => chunk !== undefined)) {
|
|
1009
|
+
vectors.push(combineColumnChunks(borrowed));
|
|
1010
|
+
} else {
|
|
1011
|
+
const valueArrays: Float64Array[] = [];
|
|
1012
|
+
for (const buffer of buffers) {
|
|
1013
|
+
const column = buffer.getColumnIfAllocated(columnName);
|
|
1014
|
+
valueArrays.push(
|
|
1015
|
+
column instanceof Float64Array
|
|
1016
|
+
? column.subarray(0, buffer._writeIndex).slice()
|
|
1017
|
+
: new F64Array(buffer._writeIndex),
|
|
1018
|
+
);
|
|
1019
|
+
}
|
|
1020
|
+
const allValues = concatenateFloat64Arrays(valueArrays);
|
|
1021
|
+
const { nullBitmap, nullCount } = concatenateNullBitmaps(buffers, columnName);
|
|
1022
|
+
vectors.push(
|
|
1023
|
+
buildColumn(
|
|
1024
|
+
buildData({
|
|
1025
|
+
type: numberType,
|
|
1026
|
+
offset: 0,
|
|
1027
|
+
length: totalRows,
|
|
1028
|
+
nullCount,
|
|
1029
|
+
data: allValues,
|
|
1030
|
+
nullBitmap,
|
|
1031
|
+
}),
|
|
1032
|
+
),
|
|
1033
|
+
);
|
|
1034
|
+
}
|
|
814
1035
|
} else if (lmaoType === 'boolean') {
|
|
815
1036
|
const valueArrays: Uint8Array[] = [];
|
|
816
1037
|
|
|
@@ -818,7 +1039,7 @@ function convertBuffersToTable(buffers: AnySpanBuffer[], systemColumnBuilder?: S
|
|
|
818
1039
|
const column = buf.getColumnIfAllocated(columnName);
|
|
819
1040
|
if (column && column instanceof Uint8Array) {
|
|
820
1041
|
const requiredBytes = Math.ceil(buf._writeIndex / 8);
|
|
821
|
-
valueArrays.push(column.subarray(0, requiredBytes));
|
|
1042
|
+
valueArrays.push(column.subarray(0, requiredBytes).slice());
|
|
822
1043
|
} else {
|
|
823
1044
|
const requiredBytes = Math.ceil(buf._writeIndex / 8);
|
|
824
1045
|
valueArrays.push(new Uint8Array(requiredBytes));
|
|
@@ -858,7 +1079,12 @@ function convertBuffersToTable(buffers: AnySpanBuffer[], systemColumnBuilder?: S
|
|
|
858
1079
|
* This is required for Arrow IPC serialization - Schema validates that
|
|
859
1080
|
* fields with same dictionary ID have identical type object references.
|
|
860
1081
|
*/
|
|
861
|
-
function buildMetadataColumnsWithFields(
|
|
1082
|
+
function buildMetadataColumnsWithFields(
|
|
1083
|
+
buffers: AnySpanBuffer[],
|
|
1084
|
+
totalRows: number,
|
|
1085
|
+
borrowChunks = false,
|
|
1086
|
+
classifiedEntryTypes?: Int8Array,
|
|
1087
|
+
): BuiltMetadataColumns {
|
|
862
1088
|
const fields: string[] = [];
|
|
863
1089
|
const vectors: Column<unknown>[] = [];
|
|
864
1090
|
|
|
@@ -866,7 +1092,7 @@ function buildMetadataColumnsWithFields(buffers: AnySpanBuffer[], totalRows: num
|
|
|
866
1092
|
// entry_type, package_name, package_file, git_sha
|
|
867
1093
|
|
|
868
1094
|
// 1. Timestamp
|
|
869
|
-
buildTimestampColumn(buffers, totalRows, fields, vectors);
|
|
1095
|
+
buildTimestampColumn(buffers, totalRows, fields, vectors, borrowChunks);
|
|
870
1096
|
|
|
871
1097
|
// 2. Trace ID dictionary (built inline from buffers)
|
|
872
1098
|
const traceIdSet = new Set<string>();
|
|
@@ -915,7 +1141,7 @@ function buildMetadataColumnsWithFields(buffers: AnySpanBuffer[], totalRows: num
|
|
|
915
1141
|
buildNonDictIdentityColumns(buffers, totalRows, fields, vectors);
|
|
916
1142
|
|
|
917
1143
|
// 7. Entry type
|
|
918
|
-
buildEntryTypeColumn(buffers, totalRows, fields, vectors);
|
|
1144
|
+
buildEntryTypeColumn(buffers, totalRows, fields, vectors, undefined, borrowChunks, classifiedEntryTypes);
|
|
919
1145
|
|
|
920
1146
|
// 8-10. Per-buffer metadata columns (package_name, package_file, git_sha)
|
|
921
1147
|
for (const [fieldName, metadataGetter] of [
|
|
@@ -951,6 +1177,51 @@ function buildMetadataColumnsWithFields(buffers: AnySpanBuffer[], totalRows: num
|
|
|
951
1177
|
return { fields, vectors };
|
|
952
1178
|
}
|
|
953
1179
|
|
|
1180
|
+
type MemoryEpochPin = { readonly buffer: ArrayBuffer; release(): void };
|
|
1181
|
+
type EpochPinnableAllocator = { pinMemoryEpoch(): MemoryEpochPin };
|
|
1182
|
+
type EpochPinnableBuffer = AnySpanBuffer & { readonly _allocator: EpochPinnableAllocator };
|
|
1183
|
+
|
|
1184
|
+
function isEpochPinnableBuffer(buffer: AnySpanBuffer): buffer is EpochPinnableBuffer {
|
|
1185
|
+
if (!('_allocator' in buffer)) return false;
|
|
1186
|
+
const allocator = Reflect.get(buffer, '_allocator');
|
|
1187
|
+
return (
|
|
1188
|
+
typeof allocator === 'object' &&
|
|
1189
|
+
allocator !== null &&
|
|
1190
|
+
typeof Reflect.get(allocator, 'pinMemoryEpoch') === 'function'
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
function createLeasedConversion(
|
|
1195
|
+
root: AnySpanBuffer,
|
|
1196
|
+
buffers: readonly AnySpanBuffer[],
|
|
1197
|
+
build: (borrowChunks: boolean) => Table,
|
|
1198
|
+
): ArrowLease {
|
|
1199
|
+
const topology = root._traceRoot._topology;
|
|
1200
|
+
topology.assertLive(root);
|
|
1201
|
+
const releaseTopology = topology.acquireLease();
|
|
1202
|
+
const generations = new Set<VocabularyGeneration>();
|
|
1203
|
+
const allocators = new Set<EpochPinnableAllocator>();
|
|
1204
|
+
for (const buffer of buffers) {
|
|
1205
|
+
generations.add(buffer._vocabularyGeneration);
|
|
1206
|
+
if (isEpochPinnableBuffer(buffer)) allocators.add(buffer._allocator);
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
const epochPins = Array.from(allocators, (allocator) => allocator.pinMemoryEpoch());
|
|
1210
|
+
// WASM linear-memory growth cannot preserve borrowed JS TypedArray views, so
|
|
1211
|
+
// its leased result uses the existing Arrow-owned copy path. JS heap buffers
|
|
1212
|
+
// expose their physical chunks directly under the topology lease.
|
|
1213
|
+
const borrowChunks = epochPins.length === 0;
|
|
1214
|
+
try {
|
|
1215
|
+
const table = build(borrowChunks);
|
|
1216
|
+
for (const pin of epochPins) pin.release();
|
|
1217
|
+
return createArrowLease(table, [...buffers, ...generations], [releaseTopology]);
|
|
1218
|
+
} catch (error) {
|
|
1219
|
+
for (const pin of epochPins) pin.release();
|
|
1220
|
+
releaseTopology();
|
|
1221
|
+
throw error;
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
|
|
954
1225
|
/**
|
|
955
1226
|
* Convert SpanBuffer (and its overflow chain) to Arrow Table
|
|
956
1227
|
*/
|
|
@@ -963,6 +1234,23 @@ export function convertToArrowTable<_T extends LogSchema = LogSchema>(
|
|
|
963
1234
|
return batch;
|
|
964
1235
|
}
|
|
965
1236
|
|
|
1237
|
+
/** Borrow JS physical Arrow chunks until the returned lease is released. */
|
|
1238
|
+
export function convertToLeasedArrowTable(
|
|
1239
|
+
buffer: AnySpanBuffer,
|
|
1240
|
+
systemColumnBuilder?: SystemColumnBuilder,
|
|
1241
|
+
): ArrowLease {
|
|
1242
|
+
const buffers: AnySpanBuffer[] = [];
|
|
1243
|
+
let segment: AnySpanBuffer | undefined = buffer;
|
|
1244
|
+
while (segment) {
|
|
1245
|
+
buffers.push(segment);
|
|
1246
|
+
segment = segment._overflow;
|
|
1247
|
+
}
|
|
1248
|
+
return createLeasedConversion(buffer, buffers, (borrowChunks) => {
|
|
1249
|
+
const table = convertToTable(buffer, systemColumnBuilder, borrowChunks);
|
|
1250
|
+
return table.numRows === 0 ? tableFromColumns({}) : table;
|
|
1251
|
+
});
|
|
1252
|
+
}
|
|
1253
|
+
|
|
966
1254
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
967
1255
|
// Tree Conversion with Shared Dictionaries
|
|
968
1256
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
@@ -979,6 +1267,7 @@ export function convertSpanTreeToArrowTable(
|
|
|
979
1267
|
_systemColumnBuilder?: SystemColumnBuilder,
|
|
980
1268
|
modulesToLogStats?: CapacityStatsEntry[],
|
|
981
1269
|
periodStartNs?: bigint,
|
|
1270
|
+
borrowChunks = false,
|
|
982
1271
|
): Table {
|
|
983
1272
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
984
1273
|
// PASS 0: Collect ALL unique schema fields from ALL buffers in the tree
|
|
@@ -986,19 +1275,27 @@ export function convertSpanTreeToArrowTable(
|
|
|
986
1275
|
// (e.g., library prefixed schemas like db_query, http_status, etc.)
|
|
987
1276
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
988
1277
|
const mergedSchemaFields = new Map<string, unknown>();
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1278
|
+
const remaps: RemapsByBuffer = new WeakMap();
|
|
1279
|
+
const enumLookupsByField = new Map<string, EnumLookupDescriptor>();
|
|
1280
|
+
|
|
1281
|
+
walkSpanTree(rootBuffer, (buffer, remapDescriptor) => {
|
|
1282
|
+
const enumLookup = resolveEnumLookupDescriptor(buffer._logSchema);
|
|
1283
|
+
if (remapDescriptor) {
|
|
1284
|
+
remaps.set(buffer, remapDescriptor);
|
|
1285
|
+
for (const [fieldName, sourceName, fieldSchema] of remapDescriptor.columns) {
|
|
1286
|
+
if (!SYSTEM_SCHEMA_FIELD_NAMES.has(fieldName) && !mergedSchemaFields.has(fieldName)) {
|
|
1287
|
+
mergedSchemaFields.set(fieldName, fieldSchema);
|
|
1288
|
+
const descriptor = enumLookup.byField[sourceName];
|
|
1289
|
+
if (descriptor) enumLookupsByField.set(fieldName, descriptor);
|
|
1290
|
+
}
|
|
998
1291
|
}
|
|
999
|
-
|
|
1000
|
-
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
for (const [fieldName, fieldSchema] of buffer._columns) {
|
|
1295
|
+
if (!SYSTEM_SCHEMA_FIELD_NAMES.has(fieldName) && !mergedSchemaFields.has(fieldName)) {
|
|
1001
1296
|
mergedSchemaFields.set(fieldName, fieldSchema);
|
|
1297
|
+
const descriptor = enumLookup.byField[fieldName];
|
|
1298
|
+
if (descriptor) enumLookupsByField.set(fieldName, descriptor);
|
|
1002
1299
|
}
|
|
1003
1300
|
}
|
|
1004
1301
|
});
|
|
@@ -1035,12 +1332,6 @@ export function convertSpanTreeToArrowTable(
|
|
|
1035
1332
|
}
|
|
1036
1333
|
}
|
|
1037
1334
|
|
|
1038
|
-
// System attribute column: message (eager category, not in user schema)
|
|
1039
|
-
// message is always present (eager allocation), so we need to handle it explicitly
|
|
1040
|
-
categoryBuilders.set('message', new DictBuilder(globalUtf8Cache));
|
|
1041
|
-
categoryMaskTransforms.set('message', undefined); // message has no masking
|
|
1042
|
-
categoryOriginalToMasked.set('message', new Map());
|
|
1043
|
-
|
|
1044
1335
|
// Metadata column dictionaries
|
|
1045
1336
|
// For traceId (metadata), use DictionaryBuilder (values not pre-encoded)
|
|
1046
1337
|
const traceIdBuilder = new DictBuilder(globalUtf8Cache);
|
|
@@ -1062,12 +1353,12 @@ export function convertSpanTreeToArrowTable(
|
|
|
1062
1353
|
}
|
|
1063
1354
|
|
|
1064
1355
|
for (const [fieldName, builder] of categoryBuilders) {
|
|
1065
|
-
const col = getAllocatedStringColumn(buffer, fieldName);
|
|
1066
1356
|
const maskTransform = categoryMaskTransforms.get(fieldName);
|
|
1067
1357
|
const originalToMasked = categoryOriginalToMasked.get(fieldName);
|
|
1068
1358
|
if (!originalToMasked) {
|
|
1069
1359
|
throw new Error(`Category originalToMasked map not found for field: ${fieldName}`);
|
|
1070
1360
|
}
|
|
1361
|
+
const col = getAllocatedStringColumn(buffer, fieldName, remaps);
|
|
1071
1362
|
if (col) {
|
|
1072
1363
|
for (let i = 0; i < buffer._writeIndex; i++) {
|
|
1073
1364
|
const originalValue = col[i];
|
|
@@ -1083,7 +1374,7 @@ export function convertSpanTreeToArrowTable(
|
|
|
1083
1374
|
}
|
|
1084
1375
|
// Also add scope values to dictionary (they may not be in columns)
|
|
1085
1376
|
// Per specs/lmao/01i_span_scope_attributes.md: scope values fill NULL cells at Arrow conversion
|
|
1086
|
-
const scopeValue = getStringScopeValue(buffer, fieldName);
|
|
1377
|
+
const scopeValue = getStringScopeValue(buffer, fieldName, remaps);
|
|
1087
1378
|
if (scopeValue !== undefined) {
|
|
1088
1379
|
let maskedScopeValue = originalToMasked.get(scopeValue);
|
|
1089
1380
|
if (maskedScopeValue === undefined) {
|
|
@@ -1095,7 +1386,7 @@ export function convertSpanTreeToArrowTable(
|
|
|
1095
1386
|
}
|
|
1096
1387
|
|
|
1097
1388
|
for (const [fieldName, builder] of textBuilders) {
|
|
1098
|
-
const col = getAllocatedStringColumn(buffer, fieldName);
|
|
1389
|
+
const col = getAllocatedStringColumn(buffer, fieldName, remaps);
|
|
1099
1390
|
const maskTransform = textMaskTransforms.get(fieldName);
|
|
1100
1391
|
const originalToMasked = textOriginalToMasked.get(fieldName);
|
|
1101
1392
|
if (!originalToMasked) {
|
|
@@ -1116,7 +1407,7 @@ export function convertSpanTreeToArrowTable(
|
|
|
1116
1407
|
}
|
|
1117
1408
|
// Also add scope values to dictionary (they may not be in columns)
|
|
1118
1409
|
// Per specs/lmao/01i_span_scope_attributes.md: scope values fill NULL cells at Arrow conversion
|
|
1119
|
-
const scopeValue = getStringScopeValue(buffer, fieldName);
|
|
1410
|
+
const scopeValue = getStringScopeValue(buffer, fieldName, remaps);
|
|
1120
1411
|
if (scopeValue !== undefined) {
|
|
1121
1412
|
let maskedScopeValue = originalToMasked.get(scopeValue);
|
|
1122
1413
|
if (maskedScopeValue === undefined) {
|
|
@@ -1166,15 +1457,6 @@ export function convertSpanTreeToArrowTable(
|
|
|
1166
1457
|
textDicts.set(name, builder.finalize(false)); // not sorted
|
|
1167
1458
|
}
|
|
1168
1459
|
|
|
1169
|
-
// Get messageDict from categoryDicts (message is handled as a category column)
|
|
1170
|
-
// If no messages were written, create an empty dictionary
|
|
1171
|
-
let messageDict = categoryDicts.get('message');
|
|
1172
|
-
if (!messageDict) {
|
|
1173
|
-
const messageBuilder = new DictBuilder(globalUtf8Cache);
|
|
1174
|
-
messageBuilder.add(''); // Single empty string entry
|
|
1175
|
-
messageDict = messageBuilder.finalize(true); // sorted
|
|
1176
|
-
}
|
|
1177
|
-
|
|
1178
1460
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
1179
1461
|
// PASS 2: Collect all buffers with non-zero rows
|
|
1180
1462
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -1198,8 +1480,11 @@ export function convertSpanTreeToArrowTable(
|
|
|
1198
1480
|
categoryDicts,
|
|
1199
1481
|
textDicts,
|
|
1200
1482
|
schemaFields,
|
|
1483
|
+
enumLookupsByField,
|
|
1201
1484
|
categoryOriginalToMasked,
|
|
1202
1485
|
textOriginalToMasked,
|
|
1486
|
+
remaps,
|
|
1487
|
+
borrowChunks,
|
|
1203
1488
|
)
|
|
1204
1489
|
: undefined;
|
|
1205
1490
|
|
|
@@ -1221,6 +1506,22 @@ export function convertSpanTreeToArrowTable(
|
|
|
1221
1506
|
return tableFromColumns({});
|
|
1222
1507
|
}
|
|
1223
1508
|
|
|
1509
|
+
/** Convert a logical trace tree while pinning every borrowed physical chunk. */
|
|
1510
|
+
export function convertSpanTreeToLeasedArrowTable(
|
|
1511
|
+
rootBuffer: AnySpanBuffer,
|
|
1512
|
+
systemColumnBuilder?: SystemColumnBuilder,
|
|
1513
|
+
modulesToLogStats?: CapacityStatsEntry[],
|
|
1514
|
+
periodStartNs?: bigint,
|
|
1515
|
+
): ArrowLease {
|
|
1516
|
+
const buffers: AnySpanBuffer[] = [];
|
|
1517
|
+
walkSpanTree(rootBuffer, (buffer) => {
|
|
1518
|
+
if (buffer._writeIndex > 0) buffers.push(buffer);
|
|
1519
|
+
});
|
|
1520
|
+
return createLeasedConversion(rootBuffer, buffers, (borrowChunks) =>
|
|
1521
|
+
convertSpanTreeToArrowTable(rootBuffer, systemColumnBuilder, modulesToLogStats, periodStartNs, borrowChunks),
|
|
1522
|
+
);
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1224
1525
|
/**
|
|
1225
1526
|
* Convert multiple buffers to a single table using pre-built dictionaries.
|
|
1226
1527
|
*
|
|
@@ -1238,12 +1539,17 @@ function convertBuffersWithSharedDicts(
|
|
|
1238
1539
|
categoryDicts: Map<string, FinalizedDictionary>,
|
|
1239
1540
|
textDicts: Map<string, FinalizedDictionary>,
|
|
1240
1541
|
schemaFields: Array<[string, unknown]>,
|
|
1542
|
+
enumLookupsByField: ReadonlyMap<string, EnumLookupDescriptor>,
|
|
1241
1543
|
categoryOriginalToMasked: Map<string, Map<string, string>>,
|
|
1242
1544
|
textOriginalToMasked: Map<string, Map<string, string>>,
|
|
1545
|
+
remaps: RemapsByBuffer,
|
|
1546
|
+
borrowChunks = false,
|
|
1243
1547
|
): Table {
|
|
1244
1548
|
const totalRows = buffers.reduce((sum, buf) => sum + buf._writeIndex, 0);
|
|
1245
1549
|
const fields: string[] = [];
|
|
1246
1550
|
const vectors: Column<unknown>[] = [];
|
|
1551
|
+
const borrowEntryTypes = canBorrowEntryTypeChunks(buffers, borrowChunks);
|
|
1552
|
+
const messageResult = buildMessageColumn(buffers, totalRows, 5, !borrowEntryTypes);
|
|
1247
1553
|
|
|
1248
1554
|
// Dictionary types with explicit IDs for IPC serialization
|
|
1249
1555
|
const traceIdType = dictionary(utf8(), traceIdDict.arrowIndexType, false, 0);
|
|
@@ -1256,7 +1562,7 @@ function convertBuffersWithSharedDicts(
|
|
|
1256
1562
|
// entry_type, package_name, package_file, git_sha
|
|
1257
1563
|
|
|
1258
1564
|
// 1. Timestamp
|
|
1259
|
-
buildTimestampColumn(buffers, totalRows, fields, vectors);
|
|
1565
|
+
buildTimestampColumn(buffers, totalRows, fields, vectors, borrowChunks);
|
|
1260
1566
|
|
|
1261
1567
|
// 2. Trace ID (using shared pre-built dictionary)
|
|
1262
1568
|
const traceIdIndices = new traceIdDict.indexArrayCtor(totalRows);
|
|
@@ -1293,7 +1599,15 @@ function convertBuffersWithSharedDicts(
|
|
|
1293
1599
|
buildNonDictIdentityColumns(buffers, totalRows, fields, vectors);
|
|
1294
1600
|
|
|
1295
1601
|
// 7. Entry type (with explicit dictionary ID for IPC)
|
|
1296
|
-
buildEntryTypeColumn(
|
|
1602
|
+
buildEntryTypeColumn(
|
|
1603
|
+
buffers,
|
|
1604
|
+
totalRows,
|
|
1605
|
+
fields,
|
|
1606
|
+
vectors,
|
|
1607
|
+
entryTypeDictType,
|
|
1608
|
+
borrowChunks,
|
|
1609
|
+
messageResult.entryTypeIndices,
|
|
1610
|
+
);
|
|
1297
1611
|
|
|
1298
1612
|
// 8-10. Per-buffer metadata columns using shared pre-built dictionaries
|
|
1299
1613
|
// Per specs/lmao/01c_context_flow_and_op_wrappers.md:
|
|
@@ -1325,52 +1639,7 @@ function convertBuffersWithSharedDicts(
|
|
|
1325
1639
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
1326
1640
|
|
|
1327
1641
|
// System attribute column: message (at fixed position 10, before user attributes)
|
|
1328
|
-
|
|
1329
|
-
const messageOriginalToMasked = categoryOriginalToMasked.get('message');
|
|
1330
|
-
if (!messageDict || !messageOriginalToMasked) {
|
|
1331
|
-
throw new Error('Message dictionary or mapping not found');
|
|
1332
|
-
}
|
|
1333
|
-
const messageFieldType = dictionary(utf8(), messageDict.arrowIndexType, false, 5);
|
|
1334
|
-
const messageIndices = new messageDict.indexArrayCtor(totalRows);
|
|
1335
|
-
const messageNullBitmap = new Uint8Array(Math.ceil(totalRows / 8));
|
|
1336
|
-
let messageRowOffset = 0;
|
|
1337
|
-
for (const buf of buffers) {
|
|
1338
|
-
const col = getAllocatedStringColumn(buf, 'message');
|
|
1339
|
-
if (col) {
|
|
1340
|
-
for (let i = 0; i < buf._writeIndex; i++) {
|
|
1341
|
-
const v = col[i];
|
|
1342
|
-
const rowIdx = messageRowOffset + i;
|
|
1343
|
-
if (v != null) {
|
|
1344
|
-
const maskedValue = messageOriginalToMasked.get(v) ?? v;
|
|
1345
|
-
messageIndices[rowIdx] = messageDict.indexMap.get(maskedValue) ?? 0;
|
|
1346
|
-
messageNullBitmap[rowIdx >>> 3] |= 1 << (rowIdx & 7);
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1349
|
-
}
|
|
1350
|
-
messageRowOffset += buf._writeIndex;
|
|
1351
|
-
}
|
|
1352
|
-
vectors.push(
|
|
1353
|
-
buildColumn(
|
|
1354
|
-
buildData({
|
|
1355
|
-
type: messageFieldType,
|
|
1356
|
-
offset: 0,
|
|
1357
|
-
length: totalRows,
|
|
1358
|
-
nullCount: 0, // message is eager, never null
|
|
1359
|
-
data: messageIndices,
|
|
1360
|
-
nullBitmap: messageNullBitmap,
|
|
1361
|
-
dictionary: buildColumn(
|
|
1362
|
-
buildData({
|
|
1363
|
-
type: utf8(),
|
|
1364
|
-
offset: 0,
|
|
1365
|
-
length: messageDict.indexMap.size,
|
|
1366
|
-
nullCount: 0,
|
|
1367
|
-
valueOffsets: messageDict.offsets,
|
|
1368
|
-
data: messageDict.data,
|
|
1369
|
-
}),
|
|
1370
|
-
),
|
|
1371
|
-
}),
|
|
1372
|
-
),
|
|
1373
|
-
);
|
|
1642
|
+
vectors.push(messageResult.column);
|
|
1374
1643
|
fields.push('message');
|
|
1375
1644
|
|
|
1376
1645
|
// System attribute column: uint64_value (for buffer metrics - op durations, counts, etc.)
|
|
@@ -1409,9 +1678,9 @@ function convertBuffersWithSharedDicts(
|
|
|
1409
1678
|
|
|
1410
1679
|
// Per specs/lmao/01i_span_scope_attributes.md: scope values fill NULL cells at Arrow conversion
|
|
1411
1680
|
for (const buf of buffers) {
|
|
1412
|
-
const col = getAllocatedStringColumn(buf, columnName);
|
|
1681
|
+
const col = getAllocatedStringColumn(buf, columnName, remaps);
|
|
1413
1682
|
// Check if this buffer has a scope value for this field
|
|
1414
|
-
const scopeValue = getStringScopeValue(buf, fieldName);
|
|
1683
|
+
const scopeValue = getStringScopeValue(buf, fieldName, remaps);
|
|
1415
1684
|
let scopeEncodedValue: number | undefined;
|
|
1416
1685
|
if (scopeValue !== undefined) {
|
|
1417
1686
|
const maskedScopeValue = originalToMasked.get(scopeValue) ?? scopeValue;
|
|
@@ -1484,9 +1753,9 @@ function convertBuffersWithSharedDicts(
|
|
|
1484
1753
|
let rowOffset = 0;
|
|
1485
1754
|
|
|
1486
1755
|
for (const buf of buffers) {
|
|
1487
|
-
const col = getAllocatedStringColumn(buf, columnName);
|
|
1756
|
+
const col = getAllocatedStringColumn(buf, columnName, remaps);
|
|
1488
1757
|
// Check if this buffer has a scope value for this field
|
|
1489
|
-
const scopeValue = getStringScopeValue(buf, fieldName);
|
|
1758
|
+
const scopeValue = getStringScopeValue(buf, fieldName, remaps);
|
|
1490
1759
|
let scopeEncodedValue: number | undefined;
|
|
1491
1760
|
if (scopeValue !== undefined) {
|
|
1492
1761
|
const maskedScopeValue = originalToMasked.get(scopeValue) ?? scopeValue;
|
|
@@ -1548,77 +1817,101 @@ function convertBuffersWithSharedDicts(
|
|
|
1548
1817
|
);
|
|
1549
1818
|
fields.push(arrowFieldName);
|
|
1550
1819
|
} else if (lmaoType === 'number') {
|
|
1551
|
-
const
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1820
|
+
const borrowed = borrowChunks
|
|
1821
|
+
? buffers.map((buffer) => {
|
|
1822
|
+
const sourceName = resolveColumnName(buffer, columnName, remaps);
|
|
1823
|
+
if (getNumberScopeValue(buffer, fieldName, remaps) !== undefined) return undefined;
|
|
1824
|
+
const column = buffer.getColumnIfAllocated(sourceName);
|
|
1825
|
+
const validity = buffer.getNullsIfAllocated(sourceName);
|
|
1826
|
+
if (!(column instanceof Float64Array) || !(validity instanceof Uint8Array)) return undefined;
|
|
1827
|
+
return buildColumn(
|
|
1828
|
+
buildData({
|
|
1829
|
+
type: float64(),
|
|
1830
|
+
offset: 0,
|
|
1831
|
+
length: buffer._writeIndex,
|
|
1832
|
+
nullCount: countNulls(validity, buffer._writeIndex),
|
|
1833
|
+
data: column.subarray(0, buffer._writeIndex),
|
|
1834
|
+
nullBitmap: validity.subarray(0, Math.ceil(buffer._writeIndex / 8)),
|
|
1835
|
+
}),
|
|
1836
|
+
);
|
|
1837
|
+
})
|
|
1838
|
+
: undefined;
|
|
1839
|
+
if (borrowed?.every((chunk): chunk is Column<unknown> => chunk !== undefined)) {
|
|
1840
|
+
vectors.push(combineColumnChunks(borrowed));
|
|
1841
|
+
} else {
|
|
1842
|
+
const allValues = new F64Array(totalRows);
|
|
1843
|
+
const nullBitmap = new Uint8Array(Math.ceil(totalRows / 8));
|
|
1844
|
+
// Start with all nulls (bits cleared) - we'll set bits as we find values
|
|
1845
|
+
let nullCount = 0;
|
|
1846
|
+
let rowOffset = 0;
|
|
1847
|
+
|
|
1848
|
+
for (const buf of buffers) {
|
|
1849
|
+
const sourceName = resolveColumnName(buf, columnName, remaps);
|
|
1850
|
+
const col = buf.getColumnIfAllocated(sourceName);
|
|
1851
|
+
const srcNulls = buf.getNullsIfAllocated(sourceName);
|
|
1852
|
+
// Check if this buffer has a scope value for this field
|
|
1853
|
+
const scopeValue = getNumberScopeValue(buf, fieldName, remaps);
|
|
1854
|
+
|
|
1855
|
+
if (col instanceof Float64Array) {
|
|
1856
|
+
allValues.set(col.subarray(0, buf._writeIndex), rowOffset);
|
|
1857
|
+
if (srcNulls) {
|
|
1858
|
+
// Process each row - direct write wins, then scope, then null
|
|
1859
|
+
for (let i = 0; i < buf._writeIndex; i++) {
|
|
1860
|
+
const srcByte = i >>> 3;
|
|
1861
|
+
const srcBit = i & 7;
|
|
1862
|
+
const isValid = (srcNulls[srcByte] & (1 << srcBit)) !== 0;
|
|
1863
|
+
const rowIdx = rowOffset + i;
|
|
1864
|
+
if (isValid) {
|
|
1865
|
+
// Direct write - mark as valid
|
|
1866
|
+
nullBitmap[rowIdx >>> 3] |= 1 << (rowIdx & 7);
|
|
1867
|
+
} else if (scopeValue !== undefined) {
|
|
1868
|
+
// No direct write, but have scope value - use it
|
|
1869
|
+
allValues[rowIdx] = scopeValue;
|
|
1870
|
+
nullBitmap[rowIdx >>> 3] |= 1 << (rowIdx & 7);
|
|
1871
|
+
} else {
|
|
1872
|
+
// No direct write and no scope - null
|
|
1873
|
+
nullCount++;
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
} else {
|
|
1877
|
+
// No null bitmap means column was allocated but no writes - check scope
|
|
1878
|
+
for (let i = 0; i < buf._writeIndex; i++) {
|
|
1879
|
+
const rowIdx = rowOffset + i;
|
|
1880
|
+
if (scopeValue !== undefined) {
|
|
1881
|
+
allValues[rowIdx] = scopeValue;
|
|
1882
|
+
nullBitmap[rowIdx >>> 3] |= 1 << (rowIdx & 7);
|
|
1883
|
+
} else {
|
|
1884
|
+
nullCount++;
|
|
1885
|
+
}
|
|
1582
1886
|
}
|
|
1583
1887
|
}
|
|
1584
|
-
} else {
|
|
1585
|
-
//
|
|
1888
|
+
} else if (scopeValue !== undefined) {
|
|
1889
|
+
// Column not allocated but we have scope - fill all rows with scope value
|
|
1586
1890
|
for (let i = 0; i < buf._writeIndex; i++) {
|
|
1587
1891
|
const rowIdx = rowOffset + i;
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
nullBitmap[rowIdx >>> 3] |= 1 << (rowIdx & 7);
|
|
1591
|
-
} else {
|
|
1592
|
-
nullCount++;
|
|
1593
|
-
}
|
|
1892
|
+
allValues[rowIdx] = scopeValue;
|
|
1893
|
+
nullBitmap[rowIdx >>> 3] |= 1 << (rowIdx & 7);
|
|
1594
1894
|
}
|
|
1895
|
+
} else {
|
|
1896
|
+
// Column doesn't exist for this buffer and no scope - all nulls
|
|
1897
|
+
nullCount += buf._writeIndex;
|
|
1595
1898
|
}
|
|
1596
|
-
|
|
1597
|
-
// Column not allocated but we have scope - fill all rows with scope value
|
|
1598
|
-
for (let i = 0; i < buf._writeIndex; i++) {
|
|
1599
|
-
const rowIdx = rowOffset + i;
|
|
1600
|
-
allValues[rowIdx] = scopeValue;
|
|
1601
|
-
nullBitmap[rowIdx >>> 3] |= 1 << (rowIdx & 7);
|
|
1602
|
-
}
|
|
1603
|
-
} else {
|
|
1604
|
-
// Column doesn't exist for this buffer and no scope - all nulls
|
|
1605
|
-
nullCount += buf._writeIndex;
|
|
1899
|
+
rowOffset += buf._writeIndex;
|
|
1606
1900
|
}
|
|
1607
|
-
rowOffset += buf._writeIndex;
|
|
1608
|
-
}
|
|
1609
1901
|
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1902
|
+
vectors.push(
|
|
1903
|
+
buildColumn(
|
|
1904
|
+
buildData({
|
|
1905
|
+
type: float64(),
|
|
1906
|
+
offset: 0,
|
|
1907
|
+
length: totalRows,
|
|
1908
|
+
nullCount,
|
|
1909
|
+
data: allValues,
|
|
1910
|
+
nullBitmap: nullCount > 0 ? nullBitmap : undefined,
|
|
1911
|
+
}),
|
|
1912
|
+
),
|
|
1913
|
+
);
|
|
1914
|
+
}
|
|
1622
1915
|
fields.push(arrowFieldName);
|
|
1623
1916
|
} else if (lmaoType === 'boolean') {
|
|
1624
1917
|
const requiredBytes = Math.ceil(totalRows / 8);
|
|
@@ -1629,10 +1922,11 @@ function convertBuffersWithSharedDicts(
|
|
|
1629
1922
|
let rowOffset = 0;
|
|
1630
1923
|
|
|
1631
1924
|
for (const buf of buffers) {
|
|
1632
|
-
const
|
|
1633
|
-
const
|
|
1925
|
+
const sourceName = resolveColumnName(buf, columnName, remaps);
|
|
1926
|
+
const col = buf.getColumnIfAllocated(sourceName);
|
|
1927
|
+
const srcNulls = buf.getNullsIfAllocated(sourceName);
|
|
1634
1928
|
// Check if this buffer has a scope value for this field
|
|
1635
|
-
const scopeValue = getBooleanScopeValue(buf, fieldName);
|
|
1929
|
+
const scopeValue = getBooleanScopeValue(buf, fieldName, remaps);
|
|
1636
1930
|
|
|
1637
1931
|
if (col instanceof Uint8Array) {
|
|
1638
1932
|
// Copy boolean values bit by bit - can't avoid loop for bit-level operations
|
|
@@ -1702,32 +1996,25 @@ function convertBuffersWithSharedDicts(
|
|
|
1702
1996
|
);
|
|
1703
1997
|
fields.push(arrowFieldName);
|
|
1704
1998
|
} else if (lmaoType === 'enum') {
|
|
1705
|
-
const
|
|
1999
|
+
const descriptor = enumLookupsByField.get(fieldName);
|
|
2000
|
+
if (!descriptor) throw new TypeError(`Enum lookup missing for field '${fieldName}'`);
|
|
2001
|
+
const enumValues = descriptor.values;
|
|
1706
2002
|
const enumUtf8 = getEnumUtf8(fieldSchema);
|
|
1707
|
-
|
|
1708
|
-
const
|
|
1709
|
-
const arrowIndexType = getArrowIndexTypeOr(fieldSchema, uint8());
|
|
2003
|
+
const indexArrayCtor = descriptor.indexArrayConstructor;
|
|
2004
|
+
const arrowIndexType = indexTypeForCount(enumValues.length);
|
|
1710
2005
|
const allIndices = new indexArrayCtor(totalRows);
|
|
1711
2006
|
const nullBitmap = new Uint8Array(Math.ceil(totalRows / 8));
|
|
1712
2007
|
// Start with all nulls (bits cleared) - we'll set bits as we find values
|
|
1713
2008
|
let nullCount = 0;
|
|
1714
2009
|
let rowOffset = 0;
|
|
1715
2010
|
|
|
1716
|
-
// Build enum value to index mapping for scope lookup
|
|
1717
|
-
const enumValueToIndex = new Map<string, number>();
|
|
1718
|
-
for (let i = 0; i < enumValues.length; i++) {
|
|
1719
|
-
enumValueToIndex.set(enumValues[i], i);
|
|
1720
|
-
}
|
|
1721
|
-
|
|
1722
2011
|
for (const buf of buffers) {
|
|
1723
|
-
const
|
|
1724
|
-
const
|
|
2012
|
+
const sourceName = resolveColumnName(buf, columnName, remaps);
|
|
2013
|
+
const col = buf.getColumnIfAllocated(sourceName);
|
|
2014
|
+
const srcNulls = buf.getNullsIfAllocated(sourceName);
|
|
1725
2015
|
// Check if this buffer has a scope value for this field
|
|
1726
|
-
const scopeValue = getStringScopeValue(buf, fieldName);
|
|
1727
|
-
|
|
1728
|
-
if (scopeValue !== undefined) {
|
|
1729
|
-
scopeEncodedValue = enumValueToIndex.get(scopeValue);
|
|
1730
|
-
}
|
|
2016
|
+
const scopeValue = getStringScopeValue(buf, fieldName, remaps);
|
|
2017
|
+
const scopeEncodedValue = scopeValue === undefined ? undefined : descriptor.encode(scopeValue);
|
|
1731
2018
|
|
|
1732
2019
|
if (col instanceof indexArrayCtor) {
|
|
1733
2020
|
allIndices.set(col.subarray(0, buf._writeIndex), rowOffset);
|
|
@@ -1801,7 +2088,7 @@ function convertBuffersWithSharedDicts(
|
|
|
1801
2088
|
} else if (lmaoType === 'binary') {
|
|
1802
2089
|
// Binary columns: raw Uint8Array or encoder-wrapped values (e.g. msgpack)
|
|
1803
2090
|
// Binary columns don't use dictionaries and are not scope-fillable
|
|
1804
|
-
const { column } = buildBinaryColumnFromBuffers(buffers, columnName, totalRows, fieldSchema);
|
|
2091
|
+
const { column } = buildBinaryColumnFromBuffers(buffers, columnName, totalRows, fieldSchema, remaps);
|
|
1805
2092
|
fields.push(arrowFieldName);
|
|
1806
2093
|
vectors.push(column);
|
|
1807
2094
|
}
|