@graphty/graph-format 0.0.0 → 0.2.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/LICENSE +21 -0
- package/README.md +216 -43
- package/dist/graph-format.d.ts +1 -0
- package/dist/graph-format.d.ts.map +1 -0
- package/dist/graph-format.js +15798 -0
- package/dist/graph-format.js.map +1 -0
- package/dist/src/builder/arena.d.ts +85 -0
- package/dist/src/builder/arena.d.ts.map +1 -0
- package/dist/src/builder/arena.js +154 -0
- package/dist/src/builder/arena.js.map +1 -0
- package/dist/src/builder/compact.d.ts +515 -0
- package/dist/src/builder/compact.d.ts.map +1 -0
- package/dist/src/builder/compact.js +1553 -0
- package/dist/src/builder/compact.js.map +1 -0
- package/dist/src/builder/counting-sort.d.ts +96 -0
- package/dist/src/builder/counting-sort.d.ts.map +1 -0
- package/dist/src/builder/counting-sort.js +430 -0
- package/dist/src/builder/counting-sort.js.map +1 -0
- package/dist/src/builder/freeze.d.ts +72 -0
- package/dist/src/builder/freeze.d.ts.map +1 -0
- package/dist/src/builder/freeze.js +548 -0
- package/dist/src/builder/freeze.js.map +1 -0
- package/dist/src/builder/graph-builder.d.ts +602 -0
- package/dist/src/builder/graph-builder.d.ts.map +1 -0
- package/dist/src/builder/graph-builder.js +1940 -0
- package/dist/src/builder/graph-builder.js.map +1 -0
- package/dist/src/builder/options.d.ts +16 -0
- package/dist/src/builder/options.d.ts.map +1 -0
- package/dist/src/builder/options.js +21 -0
- package/dist/src/builder/options.js.map +1 -0
- package/dist/src/columns/bitmap.d.ts +96 -0
- package/dist/src/columns/bitmap.d.ts.map +1 -0
- package/dist/src/columns/bitmap.js +184 -0
- package/dist/src/columns/bitmap.js.map +1 -0
- package/dist/src/columns/column.d.ts +220 -0
- package/dist/src/columns/column.d.ts.map +1 -0
- package/dist/src/columns/column.js +2109 -0
- package/dist/src/columns/column.js.map +1 -0
- package/dist/src/columns/dictionary.d.ts +60 -0
- package/dist/src/columns/dictionary.d.ts.map +1 -0
- package/dist/src/columns/dictionary.js +102 -0
- package/dist/src/columns/dictionary.js.map +1 -0
- package/dist/src/columns/growable.d.ts +198 -0
- package/dist/src/columns/growable.d.ts.map +1 -0
- package/dist/src/columns/growable.js +296 -0
- package/dist/src/columns/growable.js.map +1 -0
- package/dist/src/columns/infer.d.ts +121 -0
- package/dist/src/columns/infer.d.ts.map +1 -0
- package/dist/src/columns/infer.js +268 -0
- package/dist/src/columns/infer.js.map +1 -0
- package/dist/src/columns/remap.d.ts +143 -0
- package/dist/src/columns/remap.d.ts.map +1 -0
- package/dist/src/columns/remap.js +588 -0
- package/dist/src/columns/remap.js.map +1 -0
- package/dist/src/columns/table.d.ts +184 -0
- package/dist/src/columns/table.d.ts.map +1 -0
- package/dist/src/columns/table.js +485 -0
- package/dist/src/columns/table.js.map +1 -0
- package/dist/src/constants.d.ts +34 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +79 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/errors.d.ts +76 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +32 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/ids/edge-id-index.d.ts +77 -0
- package/dist/src/ids/edge-id-index.d.ts.map +1 -0
- package/dist/src/ids/edge-id-index.js +155 -0
- package/dist/src/ids/edge-id-index.js.map +1 -0
- package/dist/src/ids/node-id-map.d.ts +280 -0
- package/dist/src/ids/node-id-map.d.ts.map +1 -0
- package/dist/src/ids/node-id-map.js +1139 -0
- package/dist/src/ids/node-id-map.js.map +1 -0
- package/dist/src/ids/string-store.d.ts +219 -0
- package/dist/src/ids/string-store.d.ts.map +1 -0
- package/dist/src/ids/string-store.js +526 -0
- package/dist/src/ids/string-store.js.map +1 -0
- package/dist/src/index.d.ts +30 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +29 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/populate/from-csr.d.ts +61 -0
- package/dist/src/populate/from-csr.d.ts.map +1 -0
- package/dist/src/populate/from-csr.js +706 -0
- package/dist/src/populate/from-csr.js.map +1 -0
- package/dist/src/populate/from-edge-arrays.d.ts +51 -0
- package/dist/src/populate/from-edge-arrays.d.ts.map +1 -0
- package/dist/src/populate/from-edge-arrays.js +217 -0
- package/dist/src/populate/from-edge-arrays.js.map +1 -0
- package/dist/src/populate/from-records.d.ts +51 -0
- package/dist/src/populate/from-records.d.ts.map +1 -0
- package/dist/src/populate/from-records.js +447 -0
- package/dist/src/populate/from-records.js.map +1 -0
- package/dist/src/snapshot/derived.d.ts +211 -0
- package/dist/src/snapshot/derived.d.ts.map +1 -0
- package/dist/src/snapshot/derived.js +1254 -0
- package/dist/src/snapshot/derived.js.map +1 -0
- package/dist/src/snapshot/graph-meta.d.ts +23 -0
- package/dist/src/snapshot/graph-meta.d.ts.map +1 -0
- package/dist/src/snapshot/graph-meta.js +159 -0
- package/dist/src/snapshot/graph-meta.js.map +1 -0
- package/dist/src/snapshot/graph-snapshot.d.ts +509 -0
- package/dist/src/snapshot/graph-snapshot.d.ts.map +1 -0
- package/dist/src/snapshot/graph-snapshot.js +1247 -0
- package/dist/src/snapshot/graph-snapshot.js.map +1 -0
- package/dist/src/snapshot/hash.d.ts +90 -0
- package/dist/src/snapshot/hash.d.ts.map +1 -0
- package/dist/src/snapshot/hash.js +228 -0
- package/dist/src/snapshot/hash.js.map +1 -0
- package/dist/src/snapshot/queries.d.ts +74 -0
- package/dist/src/snapshot/queries.d.ts.map +1 -0
- package/dist/src/snapshot/queries.js +131 -0
- package/dist/src/snapshot/queries.js.map +1 -0
- package/dist/src/snapshot/validate.d.ts +192 -0
- package/dist/src/snapshot/validate.d.ts.map +1 -0
- package/dist/src/snapshot/validate.js +990 -0
- package/dist/src/snapshot/validate.js.map +1 -0
- package/dist/src/snapshot/views.d.ts +274 -0
- package/dist/src/snapshot/views.d.ts.map +1 -0
- package/dist/src/snapshot/views.js +856 -0
- package/dist/src/snapshot/views.js.map +1 -0
- package/dist/src/types/builder.d.ts +456 -0
- package/dist/src/types/builder.d.ts.map +1 -0
- package/dist/src/types/builder.js +11 -0
- package/dist/src/types/builder.js.map +1 -0
- package/dist/src/types/columns.d.ts +615 -0
- package/dist/src/types/columns.d.ts.map +1 -0
- package/dist/src/types/columns.js +14 -0
- package/dist/src/types/columns.js.map +1 -0
- package/dist/src/types/index.d.ts +14 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/index.js +11 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/types/internal.d.ts +172 -0
- package/dist/src/types/internal.d.ts.map +1 -0
- package/dist/src/types/internal.js +13 -0
- package/dist/src/types/internal.js.map +1 -0
- package/dist/src/types/snapshot.d.ts +801 -0
- package/dist/src/types/snapshot.d.ts.map +1 -0
- package/dist/src/types/snapshot.js +14 -0
- package/dist/src/types/snapshot.js.map +1 -0
- package/dist/src/types/wire.d.ts +196 -0
- package/dist/src/types/wire.d.ts.map +1 -0
- package/dist/src/types/wire.js +8 -0
- package/dist/src/types/wire.js.map +1 -0
- package/dist/src/util/mask.d.ts +55 -0
- package/dist/src/util/mask.d.ts.map +1 -0
- package/dist/src/util/mask.js +71 -0
- package/dist/src/util/mask.js.map +1 -0
- package/dist/src/util/options.d.ts +22 -0
- package/dist/src/util/options.d.ts.map +1 -0
- package/dist/src/util/options.js +49 -0
- package/dist/src/util/options.js.map +1 -0
- package/dist/src/util/shared-buffers.d.ts +42 -0
- package/dist/src/util/shared-buffers.d.ts.map +1 -0
- package/dist/src/util/shared-buffers.js +52 -0
- package/dist/src/util/shared-buffers.js.map +1 -0
- package/dist/src/util/typed-array.d.ts +205 -0
- package/dist/src/util/typed-array.d.ts.map +1 -0
- package/dist/src/util/typed-array.js +289 -0
- package/dist/src/util/typed-array.js.map +1 -0
- package/dist/src/wire/bytes.d.ts +69 -0
- package/dist/src/wire/bytes.d.ts.map +1 -0
- package/dist/src/wire/bytes.js +361 -0
- package/dist/src/wire/bytes.js.map +1 -0
- package/dist/src/wire/carried-views.d.ts +111 -0
- package/dist/src/wire/carried-views.d.ts.map +1 -0
- package/dist/src/wire/carried-views.js +286 -0
- package/dist/src/wire/carried-views.js.map +1 -0
- package/dist/src/wire/from-wire.d.ts +144 -0
- package/dist/src/wire/from-wire.d.ts.map +1 -0
- package/dist/src/wire/from-wire.js +1425 -0
- package/dist/src/wire/from-wire.js.map +1 -0
- package/dist/src/wire/to-wire.d.ts +171 -0
- package/dist/src/wire/to-wire.d.ts.map +1 -0
- package/dist/src/wire/to-wire.js +652 -0
- package/dist/src/wire/to-wire.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +72 -7
- package/src/builder/arena.ts +192 -0
- package/src/builder/compact.ts +1811 -0
- package/src/builder/counting-sort.ts +506 -0
- package/src/builder/freeze.ts +689 -0
- package/src/builder/graph-builder.ts +2264 -0
- package/src/builder/options.ts +29 -0
- package/src/columns/bitmap.ts +196 -0
- package/src/columns/column.ts +2574 -0
- package/src/columns/dictionary.ts +114 -0
- package/src/columns/growable.ts +350 -0
- package/src/columns/infer.ts +285 -0
- package/src/columns/remap.ts +663 -0
- package/src/columns/table.ts +568 -0
- package/src/constants.ts +89 -0
- package/src/errors.ts +115 -0
- package/src/ids/edge-id-index.ts +179 -0
- package/src/ids/node-id-map.ts +1340 -0
- package/src/ids/string-store.ts +589 -0
- package/src/index.ts +139 -0
- package/src/lib-resizable-array-buffer.d.ts +34 -0
- package/src/populate/from-csr.ts +802 -0
- package/src/populate/from-edge-arrays.ts +257 -0
- package/src/populate/from-records.ts +536 -0
- package/src/snapshot/derived.ts +1486 -0
- package/src/snapshot/graph-meta.ts +167 -0
- package/src/snapshot/graph-snapshot.ts +1503 -0
- package/src/snapshot/hash.ts +241 -0
- package/src/snapshot/queries.ts +136 -0
- package/src/snapshot/validate.ts +1108 -0
- package/src/snapshot/views.ts +943 -0
- package/src/types/builder.ts +480 -0
- package/src/types/columns.ts +727 -0
- package/src/types/index.ts +14 -0
- package/src/types/internal.ts +195 -0
- package/src/types/snapshot.ts +886 -0
- package/src/types/wire.ts +207 -0
- package/src/util/mask.ts +89 -0
- package/src/util/options.ts +57 -0
- package/src/util/shared-buffers.ts +56 -0
- package/src/util/typed-array.ts +371 -0
- package/src/wire/bytes.ts +440 -0
- package/src/wire/carried-views.ts +327 -0
- package/src/wire/from-wire.ts +1690 -0
- package/src/wire/to-wire.ts +755 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AttributeTable: a set of index-aligned columns with a fixed row count (design section 5.7). The
|
|
3
|
+
* column SET is a mutable side table of the snapshot (set / remove / rename at any time, by the
|
|
4
|
+
* snapshot owner); the row count is fixed for the life of the table (invariant I17) and column
|
|
5
|
+
* contents are frozen unless the column was declared mutable (design section 5.8). "Absent" is
|
|
6
|
+
* always null on this surface; undefined only ever means "unset row" from value(). Iteration yields
|
|
7
|
+
* columns in declaration order. At most one column per role (E_DUPLICATE_ROLE).
|
|
8
|
+
*
|
|
9
|
+
* The exported helper functions (tableWithColumns, verifyUniqueColumns, declareColumn) are for the
|
|
10
|
+
* snapshot, builder and freeze modules; they are not part of the public surface.
|
|
11
|
+
*/
|
|
12
|
+
import { type AttributeTableContract, type Column, type ColumnDeclPatch, type ColumnDomain, type ColumnInput, type ColumnOf, type ColumnRole, type Dtype, type F32, type I32, type SetOptions, type TypedArrayData, type U32 } from "../types/index.js";
|
|
13
|
+
/**
|
|
14
|
+
* The number of column-set changes a table has seen (set / remove / rename), so a cached role or name
|
|
15
|
+
* lookup can be reused while the set is unchanged.
|
|
16
|
+
* @param table - the table
|
|
17
|
+
* @returns the change count
|
|
18
|
+
*/
|
|
19
|
+
export declare function columnSetVersion(table: AttributeTable): number;
|
|
20
|
+
/**
|
|
21
|
+
* A set of columns with a fixed row count (design sections 5.7 and 12.2): `nodes` (nodeCount rows),
|
|
22
|
+
* `edges` (edgeCount rows), `graph` (1 row) and extension tables. The column set is a mutable side
|
|
23
|
+
* table; the row count is fixed; iteration is in declaration order.
|
|
24
|
+
*/
|
|
25
|
+
export declare class AttributeTable implements AttributeTableContract {
|
|
26
|
+
/** The table the columns belong to. */
|
|
27
|
+
readonly domain: ColumnDomain;
|
|
28
|
+
/** Number of rows of every column; fixed for the life of the table. */
|
|
29
|
+
readonly rowCount: number;
|
|
30
|
+
private readonly columns;
|
|
31
|
+
/** Bumped on every change of the column set (set / remove / rename), for callers that cache a lookup. */
|
|
32
|
+
private mutations;
|
|
33
|
+
/**
|
|
34
|
+
* Column names in declaration order.
|
|
35
|
+
* @returns a fresh array of the names
|
|
36
|
+
*/
|
|
37
|
+
names(): readonly string[];
|
|
38
|
+
/**
|
|
39
|
+
* Whether a column exists.
|
|
40
|
+
* @param name - the column name
|
|
41
|
+
* @returns true when present
|
|
42
|
+
*/
|
|
43
|
+
has(name: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Total lookup by name.
|
|
46
|
+
* @param name - the column name
|
|
47
|
+
* @returns the column, or null when absent
|
|
48
|
+
*/
|
|
49
|
+
get(name: string): Column | null;
|
|
50
|
+
/**
|
|
51
|
+
* Checked lookup by name.
|
|
52
|
+
* @param name - the column name
|
|
53
|
+
* @returns the column; E_UNKNOWN_COLUMN when absent
|
|
54
|
+
*/
|
|
55
|
+
require(name: string): Column;
|
|
56
|
+
/**
|
|
57
|
+
* Total lookup by name and dtype.
|
|
58
|
+
* @param name - the column name
|
|
59
|
+
* @param dtype - the expected dtype
|
|
60
|
+
* @returns the column, or null when absent or of another dtype
|
|
61
|
+
*/
|
|
62
|
+
typed<D extends Dtype>(name: string, dtype: D): ColumnOf<D> | null;
|
|
63
|
+
/**
|
|
64
|
+
* Checked lookup by name and dtype.
|
|
65
|
+
* @param name - the column name
|
|
66
|
+
* @param dtype - the expected dtype
|
|
67
|
+
* @returns the column; E_UNKNOWN_COLUMN when absent, E_COLUMN_TYPE when of another dtype
|
|
68
|
+
*/
|
|
69
|
+
requireTyped<D extends Dtype>(name: string, dtype: D): ColumnOf<D>;
|
|
70
|
+
/**
|
|
71
|
+
* The column holding a role (at most one per table).
|
|
72
|
+
* @param role - the role
|
|
73
|
+
* @returns the column, or null when no column has the role
|
|
74
|
+
*/
|
|
75
|
+
byRole(role: ColumnRole): Column | null;
|
|
76
|
+
/**
|
|
77
|
+
* Typed read of one cell honouring the column's declared default.
|
|
78
|
+
* @param name - the column name; E_UNKNOWN_COLUMN when absent
|
|
79
|
+
* @param row - the row index; E_INDEX_RANGE when out of range
|
|
80
|
+
* @returns the value, the default for an unset row, or undefined for an unset row without a default
|
|
81
|
+
*/
|
|
82
|
+
value(name: string, row: number): unknown;
|
|
83
|
+
/**
|
|
84
|
+
* Whether one cell holds a value.
|
|
85
|
+
* @param name - the column name; E_UNKNOWN_COLUMN when absent
|
|
86
|
+
* @param row - the row index (false when out of range)
|
|
87
|
+
* @returns true when set
|
|
88
|
+
*/
|
|
89
|
+
isSet(name: string, row: number): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Attach a column (design section 5.7). A typed array is adopted by reference after its length is
|
|
92
|
+
* checked (E_COLUMN_LENGTH); a u8 array from which no padded u32 view is constructible is copied
|
|
93
|
+
* unless opts.adopt is "strict" (E_COLUMN_ALIGNMENT); a view over a SharedArrayBuffer or a
|
|
94
|
+
* resizable buffer is E_UNSUPPORTED (decision D-SAB, invariant I10); a JS array builds a column of
|
|
95
|
+
* the declared dtype, or of the dtype inferred from the values (design section 5.1) when the
|
|
96
|
+
* patch names none; a Column object is moved in when its row count matches. Replaces a column of
|
|
97
|
+
* the same name. E_DUPLICATE_ROLE when the declared role is held by another column and
|
|
98
|
+
* opts.replaceRole is not set; with replaceRole the previous holder is removed.
|
|
99
|
+
* @param name - the column name
|
|
100
|
+
* @param data - a Column, a typed array, or a JS array of values
|
|
101
|
+
* @param decl - declaration fields to apply (dtype is inferred from a typed array when omitted)
|
|
102
|
+
* @param opts - role replacement and u8 adoption options
|
|
103
|
+
* @returns the attached column (`column.data !== data` only when a u8 array was copied)
|
|
104
|
+
*/
|
|
105
|
+
set(name: string, data: Column | TypedArrayData | readonly unknown[], decl?: ColumnDeclPatch, opts?: SetOptions): Column;
|
|
106
|
+
/**
|
|
107
|
+
* Remove a column.
|
|
108
|
+
* @param name - the column name
|
|
109
|
+
* @returns true when a column was removed
|
|
110
|
+
*/
|
|
111
|
+
remove(name: string): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Rename a column in place (declaration order kept). The Column object is re-wrapped under the new
|
|
114
|
+
* name; its storage is shared with the previous object.
|
|
115
|
+
* @param from - the current name; E_UNKNOWN_COLUMN when absent
|
|
116
|
+
* @param to - the new name; E_COLUMN_EXISTS when another column has it
|
|
117
|
+
*/
|
|
118
|
+
rename(from: string, to: string): void;
|
|
119
|
+
/**
|
|
120
|
+
* The array a GPU binds for a column (design section 10.4): its own data for the direct dtypes,
|
|
121
|
+
* the padded u32 view for u8, the packed words for bool, the codes for dict, and a cached f32 copy
|
|
122
|
+
* for f64.
|
|
123
|
+
* @param name - the column name; E_UNKNOWN_COLUMN when absent
|
|
124
|
+
* @returns the bindable array; E_GPU_INELIGIBLE for string / list / json
|
|
125
|
+
*/
|
|
126
|
+
gpuView(name: string): U32 | I32 | F32;
|
|
127
|
+
/**
|
|
128
|
+
* A new table with the same columns: the Column objects are shared, the set is independent.
|
|
129
|
+
* @returns the cloned table
|
|
130
|
+
*/
|
|
131
|
+
clone(): AttributeTable;
|
|
132
|
+
/**
|
|
133
|
+
* Iterate the columns in declaration order.
|
|
134
|
+
* @returns an iterator over the columns
|
|
135
|
+
*/
|
|
136
|
+
[Symbol.iterator](): IterableIterator<Column>;
|
|
137
|
+
/**
|
|
138
|
+
* Move a Column object in: checked for row count and re-wrapped when its name, domain or
|
|
139
|
+
* declaration differ from the target slot.
|
|
140
|
+
* @param name - the target name
|
|
141
|
+
* @param column - the column
|
|
142
|
+
* @param decl - an optional declaration patch
|
|
143
|
+
* @returns the column to store (the same object when nothing changes)
|
|
144
|
+
*/
|
|
145
|
+
private adoptColumn;
|
|
146
|
+
private checkColumn;
|
|
147
|
+
/**
|
|
148
|
+
* Enforce "at most one column per role": E_DUPLICATE_ROLE when another column holds the role,
|
|
149
|
+
* unless replaceRole, in which case that column is removed.
|
|
150
|
+
* @param name - the column being attached (a column may keep its own role)
|
|
151
|
+
* @param role - the role being attached, or null
|
|
152
|
+
* @param replaceRole - whether to evict the previous holder
|
|
153
|
+
*/
|
|
154
|
+
private checkRole;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Create an empty table.
|
|
158
|
+
* @param domain - the table's domain
|
|
159
|
+
* @param rowCount - the fixed row count
|
|
160
|
+
* @returns a table with no columns
|
|
161
|
+
*/
|
|
162
|
+
export declare function createTable(domain: ColumnDomain, rowCount: number): AttributeTable;
|
|
163
|
+
/**
|
|
164
|
+
* A cloned table plus the given columns (the column half of snapshot.withColumns(), design section
|
|
165
|
+
* 7.3): the Column objects of the source are shared, the set is new, and each entry of `columns` is
|
|
166
|
+
* attached through set() (a typed array, or a ColumnInput carrying data and a declaration patch).
|
|
167
|
+
* @param table - the source table
|
|
168
|
+
* @param columns - the columns to add or replace, keyed by name
|
|
169
|
+
* @returns the new table
|
|
170
|
+
*/
|
|
171
|
+
export declare function tableWithColumns(table: AttributeTable, columns: Readonly<Record<string, TypedArrayData | ColumnInput>>): AttributeTable;
|
|
172
|
+
/**
|
|
173
|
+
* Enforce a unique column over its set rows (design section 5.5; the freeze step 10 hook):
|
|
174
|
+
* E_DUPLICATE_EDGE_ID for an edge column and E_DUPLICATE_ID for every other domain, with the
|
|
175
|
+
* duplicated value and both rows in details.
|
|
176
|
+
* @param column - a column declared unique
|
|
177
|
+
*/
|
|
178
|
+
export declare function verifyUniqueColumn(column: Column): void;
|
|
179
|
+
/**
|
|
180
|
+
* Enforce every unique column of a table (freeze step 10).
|
|
181
|
+
* @param table - the table to check
|
|
182
|
+
*/
|
|
183
|
+
export declare function verifyUniqueColumns(table: AttributeTable): void;
|
|
184
|
+
//# sourceMappingURL=table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/columns/table.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AttributeTable: a set of index-aligned columns with a fixed row count (design section 5.7). The
|
|
3
|
+
* column SET is a mutable side table of the snapshot (set / remove / rename at any time, by the
|
|
4
|
+
* snapshot owner); the row count is fixed for the life of the table (invariant I17) and column
|
|
5
|
+
* contents are frozen unless the column was declared mutable (design section 5.8). "Absent" is
|
|
6
|
+
* always null on this surface; undefined only ever means "unset row" from value(). Iteration yields
|
|
7
|
+
* columns in declaration order. At most one column per role (E_DUPLICATE_ROLE).
|
|
8
|
+
*
|
|
9
|
+
* The exported helper functions (tableWithColumns, verifyUniqueColumns, declareColumn) are for the
|
|
10
|
+
* snapshot, builder and freeze modules; they are not part of the public surface.
|
|
11
|
+
*/
|
|
12
|
+
import { GraphFormatError } from "../errors.js";
|
|
13
|
+
import { assertOneOf } from "../util/options.js";
|
|
14
|
+
import { claimHolder, holderCount, isShared, noteShared } from "../util/shared-buffers.js";
|
|
15
|
+
import { bitmapGet } from "./bitmap.js";
|
|
16
|
+
import { columnBuffers, columnFromTypedArray, columnFromValues, gpuViewOf, isPackageColumn, metaToDecl, resolveColumnMeta, rewrapColumn, } from "./column.js";
|
|
17
|
+
/**
|
|
18
|
+
* Whether a set() payload is a typed array (as opposed to a Column object or a JS array).
|
|
19
|
+
* @param data - the payload
|
|
20
|
+
* @returns true for one of the five typed-array classes
|
|
21
|
+
*/
|
|
22
|
+
function isTypedArrayData(data) {
|
|
23
|
+
return (data instanceof Uint32Array ||
|
|
24
|
+
data instanceof Int32Array ||
|
|
25
|
+
data instanceof Float32Array ||
|
|
26
|
+
data instanceof Float64Array ||
|
|
27
|
+
data instanceof Uint8Array);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Whether a set() payload is a Column object (duck-typed on the members every column has).
|
|
31
|
+
* @param data - the payload
|
|
32
|
+
* @returns true for a Column
|
|
33
|
+
*/
|
|
34
|
+
function isColumn(data) {
|
|
35
|
+
if (typeof data !== "object" || data === null || Array.isArray(data) || isTypedArrayData(data)) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const candidate = data;
|
|
39
|
+
return (typeof candidate.dtype === "string" &&
|
|
40
|
+
typeof candidate.meta === "object" &&
|
|
41
|
+
typeof candidate.length === "number");
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The number of column-set changes a table has seen (set / remove / rename), so a cached role or name
|
|
45
|
+
* lookup can be reused while the set is unchanged.
|
|
46
|
+
* @param table - the table
|
|
47
|
+
* @returns the change count
|
|
48
|
+
*/
|
|
49
|
+
export function columnSetVersion(table) {
|
|
50
|
+
return table.mutations;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Record a table as a holder of a column and of every buffer the column views (design section 9.1).
|
|
54
|
+
* @param column - the column being attached
|
|
55
|
+
*/
|
|
56
|
+
function claimColumn(column) {
|
|
57
|
+
claimHolder(column);
|
|
58
|
+
for (const buffer of columnBuffers(column)) {
|
|
59
|
+
claimHolder(buffer);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* A set of columns with a fixed row count (design sections 5.7 and 12.2): `nodes` (nodeCount rows),
|
|
64
|
+
* `edges` (edgeCount rows), `graph` (1 row) and extension tables. The column set is a mutable side
|
|
65
|
+
* table; the row count is fixed; iteration is in declaration order.
|
|
66
|
+
*/
|
|
67
|
+
export class AttributeTable {
|
|
68
|
+
/**
|
|
69
|
+
* Create a table from wrapped columns (the constructor the freeze pipeline, fromCsr and the wire
|
|
70
|
+
* reader use). Every column must have the table's row count and domain, names must be unique and
|
|
71
|
+
* at most one column may hold each role.
|
|
72
|
+
* @param parts - the domain, the row count and the columns in declaration order
|
|
73
|
+
* @internal
|
|
74
|
+
*/
|
|
75
|
+
constructor(parts) {
|
|
76
|
+
/** Bumped on every change of the column set (set / remove / rename), for callers that cache a lookup. */
|
|
77
|
+
this.mutations = 0;
|
|
78
|
+
const { domain, rowCount } = parts;
|
|
79
|
+
if (!(Number.isInteger(rowCount) && rowCount >= 0)) {
|
|
80
|
+
throw new GraphFormatError("E_COLUMN_LENGTH", `invalid row count ${rowCount} for a ${domain} table`, {
|
|
81
|
+
domain,
|
|
82
|
+
found: rowCount,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
this.domain = domain;
|
|
86
|
+
this.rowCount = rowCount;
|
|
87
|
+
this.columns = new Map();
|
|
88
|
+
for (const column of parts.columns) {
|
|
89
|
+
const { name } = column.meta;
|
|
90
|
+
if (this.columns.has(name)) {
|
|
91
|
+
throw new GraphFormatError("E_COLUMN_EXISTS", `column "${name}" is declared twice`, { column: name });
|
|
92
|
+
}
|
|
93
|
+
this.checkColumn(name, column);
|
|
94
|
+
this.checkRole(name, column.meta.role, false);
|
|
95
|
+
this.columns.set(name, column);
|
|
96
|
+
claimColumn(column);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Column names in declaration order.
|
|
101
|
+
* @returns a fresh array of the names
|
|
102
|
+
*/
|
|
103
|
+
names() {
|
|
104
|
+
return [...this.columns.keys()];
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Whether a column exists.
|
|
108
|
+
* @param name - the column name
|
|
109
|
+
* @returns true when present
|
|
110
|
+
*/
|
|
111
|
+
has(name) {
|
|
112
|
+
return this.columns.has(name);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Total lookup by name.
|
|
116
|
+
* @param name - the column name
|
|
117
|
+
* @returns the column, or null when absent
|
|
118
|
+
*/
|
|
119
|
+
get(name) {
|
|
120
|
+
return this.columns.get(name) ?? null;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Checked lookup by name.
|
|
124
|
+
* @param name - the column name
|
|
125
|
+
* @returns the column; E_UNKNOWN_COLUMN when absent
|
|
126
|
+
*/
|
|
127
|
+
require(name) {
|
|
128
|
+
const column = this.columns.get(name);
|
|
129
|
+
if (column === undefined) {
|
|
130
|
+
throw new GraphFormatError("E_UNKNOWN_COLUMN", `no ${this.domain} column named "${name}"`, {
|
|
131
|
+
column: name,
|
|
132
|
+
domain: this.domain,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return column;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Total lookup by name and dtype.
|
|
139
|
+
* @param name - the column name
|
|
140
|
+
* @param dtype - the expected dtype
|
|
141
|
+
* @returns the column, or null when absent or of another dtype
|
|
142
|
+
*/
|
|
143
|
+
typed(name, dtype) {
|
|
144
|
+
const column = this.columns.get(name);
|
|
145
|
+
if (column === undefined || column.dtype !== dtype) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
return column;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Checked lookup by name and dtype.
|
|
152
|
+
* @param name - the column name
|
|
153
|
+
* @param dtype - the expected dtype
|
|
154
|
+
* @returns the column; E_UNKNOWN_COLUMN when absent, E_COLUMN_TYPE when of another dtype
|
|
155
|
+
*/
|
|
156
|
+
requireTyped(name, dtype) {
|
|
157
|
+
const column = this.require(name);
|
|
158
|
+
if (column.dtype !== dtype) {
|
|
159
|
+
throw new GraphFormatError("E_COLUMN_TYPE", `column "${name}" is ${column.dtype}, expected ${dtype}`, {
|
|
160
|
+
column: name,
|
|
161
|
+
expected: dtype,
|
|
162
|
+
found: column.dtype,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
return column;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* The column holding a role (at most one per table).
|
|
169
|
+
* @param role - the role
|
|
170
|
+
* @returns the column, or null when no column has the role
|
|
171
|
+
*/
|
|
172
|
+
byRole(role) {
|
|
173
|
+
for (const column of this.columns.values()) {
|
|
174
|
+
if (column.meta.role === role) {
|
|
175
|
+
return column;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Typed read of one cell honouring the column's declared default.
|
|
182
|
+
* @param name - the column name; E_UNKNOWN_COLUMN when absent
|
|
183
|
+
* @param row - the row index; E_INDEX_RANGE when out of range
|
|
184
|
+
* @returns the value, the default for an unset row, or undefined for an unset row without a default
|
|
185
|
+
*/
|
|
186
|
+
value(name, row) {
|
|
187
|
+
return this.require(name).value(row);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Whether one cell holds a value.
|
|
191
|
+
* @param name - the column name; E_UNKNOWN_COLUMN when absent
|
|
192
|
+
* @param row - the row index (false when out of range)
|
|
193
|
+
* @returns true when set
|
|
194
|
+
*/
|
|
195
|
+
isSet(name, row) {
|
|
196
|
+
return this.require(name).isSet(row);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Attach a column (design section 5.7). A typed array is adopted by reference after its length is
|
|
200
|
+
* checked (E_COLUMN_LENGTH); a u8 array from which no padded u32 view is constructible is copied
|
|
201
|
+
* unless opts.adopt is "strict" (E_COLUMN_ALIGNMENT); a view over a SharedArrayBuffer or a
|
|
202
|
+
* resizable buffer is E_UNSUPPORTED (decision D-SAB, invariant I10); a JS array builds a column of
|
|
203
|
+
* the declared dtype, or of the dtype inferred from the values (design section 5.1) when the
|
|
204
|
+
* patch names none; a Column object is moved in when its row count matches. Replaces a column of
|
|
205
|
+
* the same name. E_DUPLICATE_ROLE when the declared role is held by another column and
|
|
206
|
+
* opts.replaceRole is not set; with replaceRole the previous holder is removed.
|
|
207
|
+
* @param name - the column name
|
|
208
|
+
* @param data - a Column, a typed array, or a JS array of values
|
|
209
|
+
* @param decl - declaration fields to apply (dtype is inferred from a typed array when omitted)
|
|
210
|
+
* @param opts - role replacement and u8 adoption options
|
|
211
|
+
* @returns the attached column (`column.data !== data` only when a u8 array was copied)
|
|
212
|
+
*/
|
|
213
|
+
set(name, data, decl, opts) {
|
|
214
|
+
const patch = decl ?? {};
|
|
215
|
+
let column;
|
|
216
|
+
if (isTypedArrayData(data)) {
|
|
217
|
+
const adopt = assertOneOf("adopt", opts?.adopt, ["copy", "strict"]) ?? "copy";
|
|
218
|
+
column = columnFromTypedArray(this.domain, this.rowCount, name, data, patch, adopt);
|
|
219
|
+
}
|
|
220
|
+
else if (Array.isArray(data)) {
|
|
221
|
+
column = columnFromValues(this.domain, this.rowCount, name, data, patch);
|
|
222
|
+
}
|
|
223
|
+
else if (isColumn(data)) {
|
|
224
|
+
if (!isPackageColumn(data)) {
|
|
225
|
+
throw new GraphFormatError("E_COLUMN_TYPE", `column "${name}": not a Column of this package`, {
|
|
226
|
+
column: name,
|
|
227
|
+
reason: "foreign column",
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
column = this.adoptColumn(name, data, decl);
|
|
231
|
+
if (column !== data && holderCount(data) > 0) {
|
|
232
|
+
// a re-wrapped column shares every buffer with `data`, which another table still holds
|
|
233
|
+
noteShared(column);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
throw new GraphFormatError("E_COLUMN_TYPE", `column "${name}": unsupported data (${typeof data})`, {
|
|
238
|
+
column: name,
|
|
239
|
+
found: typeof data,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
this.checkRole(name, column.meta.role, opts?.replaceRole ?? false);
|
|
243
|
+
const previous = this.columns.get(name);
|
|
244
|
+
if (previous !== column) {
|
|
245
|
+
// a Column object moved in from another table gains a second holder, and so does every
|
|
246
|
+
// buffer it views (a zero-copy slice of another table's column, design section 9.1);
|
|
247
|
+
// re-wrapping this table's own column under a patch adds no holder of its buffers
|
|
248
|
+
claimHolder(column);
|
|
249
|
+
if (previous !== data) {
|
|
250
|
+
for (const buffer of columnBuffers(column)) {
|
|
251
|
+
claimHolder(buffer);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// Map.set on an existing key keeps its position, so a replacement keeps the declaration order
|
|
256
|
+
this.columns.set(name, column);
|
|
257
|
+
this.mutations++;
|
|
258
|
+
return column;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Remove a column.
|
|
262
|
+
* @param name - the column name
|
|
263
|
+
* @returns true when a column was removed
|
|
264
|
+
*/
|
|
265
|
+
remove(name) {
|
|
266
|
+
const removed = this.columns.delete(name);
|
|
267
|
+
if (removed) {
|
|
268
|
+
this.mutations++;
|
|
269
|
+
}
|
|
270
|
+
return removed;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Rename a column in place (declaration order kept). The Column object is re-wrapped under the new
|
|
274
|
+
* name; its storage is shared with the previous object.
|
|
275
|
+
* @param from - the current name; E_UNKNOWN_COLUMN when absent
|
|
276
|
+
* @param to - the new name; E_COLUMN_EXISTS when another column has it
|
|
277
|
+
*/
|
|
278
|
+
rename(from, to) {
|
|
279
|
+
const column = this.require(from);
|
|
280
|
+
if (from === to) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
if (this.columns.has(to)) {
|
|
284
|
+
throw new GraphFormatError("E_COLUMN_EXISTS", `cannot rename "${from}": a column named "${to}" exists`, {
|
|
285
|
+
column: to,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
const renamed = rewrapColumn(column, resolveColumnMeta(to, this.domain, metaToDecl(column.meta)));
|
|
289
|
+
// the same table keeps holding the same buffers: only the new Column object is claimed
|
|
290
|
+
claimHolder(renamed);
|
|
291
|
+
if (isShared(column)) {
|
|
292
|
+
noteShared(renamed);
|
|
293
|
+
}
|
|
294
|
+
const entries = [...this.columns.entries()];
|
|
295
|
+
this.columns.clear();
|
|
296
|
+
for (const [name, existing] of entries) {
|
|
297
|
+
if (name === from) {
|
|
298
|
+
this.columns.set(to, renamed);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
this.columns.set(name, existing);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
this.mutations++;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* The array a GPU binds for a column (design section 10.4): its own data for the direct dtypes,
|
|
308
|
+
* the padded u32 view for u8, the packed words for bool, the codes for dict, and a cached f32 copy
|
|
309
|
+
* for f64.
|
|
310
|
+
* @param name - the column name; E_UNKNOWN_COLUMN when absent
|
|
311
|
+
* @returns the bindable array; E_GPU_INELIGIBLE for string / list / json
|
|
312
|
+
*/
|
|
313
|
+
gpuView(name) {
|
|
314
|
+
return gpuViewOf(this.require(name));
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* A new table with the same columns: the Column objects are shared, the set is independent.
|
|
318
|
+
* @returns the cloned table
|
|
319
|
+
*/
|
|
320
|
+
clone() {
|
|
321
|
+
return new AttributeTable({
|
|
322
|
+
domain: this.domain,
|
|
323
|
+
rowCount: this.rowCount,
|
|
324
|
+
columns: [...this.columns.values()],
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Iterate the columns in declaration order.
|
|
329
|
+
* @returns an iterator over the columns
|
|
330
|
+
*/
|
|
331
|
+
[Symbol.iterator]() {
|
|
332
|
+
return this.columns.values();
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Move a Column object in: checked for row count and re-wrapped when its name, domain or
|
|
336
|
+
* declaration differ from the target slot.
|
|
337
|
+
* @param name - the target name
|
|
338
|
+
* @param column - the column
|
|
339
|
+
* @param decl - an optional declaration patch
|
|
340
|
+
* @returns the column to store (the same object when nothing changes)
|
|
341
|
+
*/
|
|
342
|
+
adoptColumn(name, column, decl) {
|
|
343
|
+
this.checkColumn(name, column);
|
|
344
|
+
const { meta } = column;
|
|
345
|
+
const unchanged = decl === undefined && meta.name === name && meta.domain === this.domain;
|
|
346
|
+
if (unchanged) {
|
|
347
|
+
return column;
|
|
348
|
+
}
|
|
349
|
+
const merged = { ...metaToDecl(meta), ...decl };
|
|
350
|
+
if (decl?.fill === undefined) {
|
|
351
|
+
merged.fill = meta.fill;
|
|
352
|
+
}
|
|
353
|
+
return rewrapColumn(column, resolveColumnMeta(name, this.domain, merged));
|
|
354
|
+
}
|
|
355
|
+
checkColumn(name, column) {
|
|
356
|
+
if (column.length !== this.rowCount) {
|
|
357
|
+
throw new GraphFormatError("E_COLUMN_LENGTH", `column "${name}" has ${column.length} rows; the ${this.domain} table has ${this.rowCount}`, { column: name, expected: this.rowCount, found: column.length });
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Enforce "at most one column per role": E_DUPLICATE_ROLE when another column holds the role,
|
|
362
|
+
* unless replaceRole, in which case that column is removed.
|
|
363
|
+
* @param name - the column being attached (a column may keep its own role)
|
|
364
|
+
* @param role - the role being attached, or null
|
|
365
|
+
* @param replaceRole - whether to evict the previous holder
|
|
366
|
+
*/
|
|
367
|
+
checkRole(name, role, replaceRole) {
|
|
368
|
+
if (role === null) {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
for (const [otherName, other] of this.columns) {
|
|
372
|
+
if (otherName !== name && other.meta.role === role) {
|
|
373
|
+
if (!replaceRole) {
|
|
374
|
+
throw new GraphFormatError("E_DUPLICATE_ROLE", `role "${role}" is already held by column "${otherName}" in the ${this.domain} table`, { role, column: name, holder: otherName });
|
|
375
|
+
}
|
|
376
|
+
this.columns.delete(otherName);
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Create an empty table.
|
|
384
|
+
* @param domain - the table's domain
|
|
385
|
+
* @param rowCount - the fixed row count
|
|
386
|
+
* @returns a table with no columns
|
|
387
|
+
*/
|
|
388
|
+
export function createTable(domain, rowCount) {
|
|
389
|
+
return new AttributeTable({ domain, rowCount, columns: [] });
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* A cloned table plus the given columns (the column half of snapshot.withColumns(), design section
|
|
393
|
+
* 7.3): the Column objects of the source are shared, the set is new, and each entry of `columns` is
|
|
394
|
+
* attached through set() (a typed array, or a ColumnInput carrying data and a declaration patch).
|
|
395
|
+
* @param table - the source table
|
|
396
|
+
* @param columns - the columns to add or replace, keyed by name
|
|
397
|
+
* @returns the new table
|
|
398
|
+
*/
|
|
399
|
+
export function tableWithColumns(table, columns) {
|
|
400
|
+
const out = table.clone();
|
|
401
|
+
for (const name of Object.keys(columns)) {
|
|
402
|
+
const input = columns[name];
|
|
403
|
+
if (isTypedArrayData(input)) {
|
|
404
|
+
out.set(name, input);
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
out.set(name, input.data, input.decl);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return out;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* The comparable key of one set cell for uniqueness checks: the number, string, boolean or
|
|
414
|
+
* dictionary value; json values are compared by their JSON text.
|
|
415
|
+
* @param column - the column
|
|
416
|
+
* @param row - a set row
|
|
417
|
+
* @returns the key
|
|
418
|
+
*/
|
|
419
|
+
function uniqueKey(column, row) {
|
|
420
|
+
const { dtype } = column;
|
|
421
|
+
switch (dtype) {
|
|
422
|
+
case "f32":
|
|
423
|
+
case "f64":
|
|
424
|
+
case "i32":
|
|
425
|
+
case "u32":
|
|
426
|
+
case "u8":
|
|
427
|
+
if (column.meta.components === 1) {
|
|
428
|
+
return column.data[row];
|
|
429
|
+
}
|
|
430
|
+
return Array.from(column.data.subarray(row * column.meta.components, (row + 1) * column.meta.components)).join(",");
|
|
431
|
+
case "bool":
|
|
432
|
+
return bitmapGet(column.data, row);
|
|
433
|
+
case "dict":
|
|
434
|
+
return column.codes[row];
|
|
435
|
+
case "string":
|
|
436
|
+
return column.valueAt(row);
|
|
437
|
+
case "list":
|
|
438
|
+
return JSON.stringify(column.sliceOf(row));
|
|
439
|
+
case "json":
|
|
440
|
+
return JSON.stringify(column.values[row]);
|
|
441
|
+
default: {
|
|
442
|
+
const name = dtype;
|
|
443
|
+
throw new GraphFormatError("E_COLUMN_TYPE", `unknown dtype ${name}`, { dtype: name });
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Enforce a unique column over its set rows (design section 5.5; the freeze step 10 hook):
|
|
449
|
+
* E_DUPLICATE_EDGE_ID for an edge column and E_DUPLICATE_ID for every other domain, with the
|
|
450
|
+
* duplicated value and both rows in details.
|
|
451
|
+
* @param column - a column declared unique
|
|
452
|
+
*/
|
|
453
|
+
export function verifyUniqueColumn(column) {
|
|
454
|
+
if (!column.meta.unique) {
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
const seen = new Map();
|
|
458
|
+
for (let row = 0; row < column.length; row++) {
|
|
459
|
+
if (!column.isSet(row)) {
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
const key = uniqueKey(column, row);
|
|
463
|
+
const first = seen.get(key);
|
|
464
|
+
if (first !== undefined) {
|
|
465
|
+
const code = column.meta.domain === "edge" ? "E_DUPLICATE_EDGE_ID" : "E_DUPLICATE_ID";
|
|
466
|
+
throw new GraphFormatError(code, `column "${column.meta.name}" is unique but rows ${first} and ${row} hold the same value`, {
|
|
467
|
+
column: column.meta.name,
|
|
468
|
+
domain: column.meta.domain,
|
|
469
|
+
rows: [first, row],
|
|
470
|
+
value: column.value(row),
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
seen.set(key, row);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Enforce every unique column of a table (freeze step 10).
|
|
478
|
+
* @param table - the table to check
|
|
479
|
+
*/
|
|
480
|
+
export function verifyUniqueColumns(table) {
|
|
481
|
+
for (const column of table) {
|
|
482
|
+
verifyUniqueColumn(column);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
//# sourceMappingURL=table.js.map
|