@platforma-sdk/model 1.10.12 → 1.13.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.
@@ -1,7 +1,16 @@
1
- import { TreeNodeAccessor } from "../accessor";
1
+ import { TreeNodeAccessor } from '../accessor';
2
2
 
3
- export const ResourceMapResourceTypeName = 'PColumnData/ResourceMap';
4
- export const ResourceMapResourcePartitionedTypeName = 'PColumnData/Partitioned/ResourceMap';
3
+ const PCD_PREFIX = 'PColumnData/';
4
+
5
+ export const RT_RESOURCE_MAP = PCD_PREFIX + 'ResourceMap';
6
+ export const RT_RESOURCE_MAP_PARTITIONED = PCD_PREFIX + 'Partitioned/ResourceMap';
7
+
8
+ export const RT_JSON_PARTITIONED = PCD_PREFIX + 'JsonPartitioned';
9
+ export const RT_BINARY_PARTITIONED = PCD_PREFIX + 'BinaryPartitioned';
10
+
11
+ const PCD_SUP_PREFIX = PCD_PREFIX + 'Partitioned/';
12
+ export const RT_JSON_SUPER_PARTITIONED = PCD_SUP_PREFIX + 'JsonPartitioned';
13
+ export const RT_BINARY_SUPER_PARTITIONED = PCD_SUP_PREFIX + 'BinaryPartitioned';
5
14
 
6
15
  export type PColumnKey = (string | number)[];
7
16
 
@@ -24,7 +33,7 @@ function populateResourceMapData<T>(
24
33
  ): boolean {
25
34
  if (acc === undefined) return false;
26
35
  switch (acc.resourceType.name) {
27
- case ResourceMapResourceTypeName: {
36
+ case RT_RESOURCE_MAP: {
28
37
  let isComplete = acc.getInputsLocked();
29
38
  for (const keyStr of acc.listInputFields()) {
30
39
  const value = acc.resolve({ field: keyStr, assertFieldType: 'Input' });
@@ -35,14 +44,20 @@ function populateResourceMapData<T>(
35
44
  }
36
45
  return isComplete;
37
46
  }
38
- case ResourceMapResourcePartitionedTypeName: {
47
+ case RT_RESOURCE_MAP_PARTITIONED: {
39
48
  let isComplete = acc.getInputsLocked();
40
49
  for (const keyStr of acc.listInputFields()) {
41
50
  const value = acc.resolve({ field: keyStr, assertFieldType: 'Input' });
42
51
  if (value === undefined) isComplete = false;
43
52
  else {
44
53
  const key = [...keyPrefix, ...JSON.parse(keyStr)] as PColumnKey;
45
- const populateResult = populateResourceMapData(value, resourceParser, data, key, addEntriesWithNoData)
54
+ const populateResult = populateResourceMapData(
55
+ value,
56
+ resourceParser,
57
+ data,
58
+ key,
59
+ addEntriesWithNoData
60
+ );
46
61
  isComplete = isComplete && populateResult;
47
62
  }
48
63
  }
@@ -72,3 +87,123 @@ export function parseResourceMap<T>(
72
87
  const isComplete = populateResourceMapData(acc, resourceParser, data, [], addEntriesWithNoData);
73
88
  return { isComplete, data };
74
89
  }
90
+
91
+
92
+ export type PColumnKeyList = {
93
+ /** array of keys */
94
+ data: PColumnKey[];
95
+ /** length of partition key */
96
+ keyLength: number;
97
+ };
98
+
99
+ const removeIndexSuffix = (keyStr: string): string | undefined => {
100
+ if (keyStr.endsWith('.index')) {
101
+ return undefined;
102
+ } else if (keyStr.endsWith('.values')) {
103
+ return keyStr.substring(0, keyStr.length - 7);
104
+ } else {
105
+ throw Error(`key must ends on .index/.values for binary p-column, got: ${keyStr}`);
106
+ }
107
+ };
108
+
109
+ // @TODO define a class with various resource map operations
110
+ /** Returns a list of all partition keys appeared in the p-column */
111
+ export function getPartitionKeysList(
112
+ acc: TreeNodeAccessor | undefined
113
+ ): PColumnKeyList | undefined {
114
+ if (!acc) return undefined;
115
+
116
+ const rt = acc.resourceType.name;
117
+ const meta = acc.getDataAsJson<Record<string, number>>();
118
+ const data: PColumnKey[] = [];
119
+
120
+ let keyLength = 0;
121
+ // @TODO validate meta shape
122
+ switch (rt) {
123
+ case RT_RESOURCE_MAP:
124
+ keyLength = meta['keyLength'];
125
+ break;
126
+
127
+ case RT_RESOURCE_MAP_PARTITIONED:
128
+ keyLength = meta['partitionKeyLength'] + meta['keyLength'];
129
+ break;
130
+
131
+ case RT_JSON_PARTITIONED:
132
+ case RT_BINARY_PARTITIONED:
133
+ keyLength = meta['partitionKeyLength'];
134
+ break;
135
+
136
+ case RT_BINARY_SUPER_PARTITIONED:
137
+ case RT_JSON_SUPER_PARTITIONED:
138
+ keyLength = meta['superPartitionKeyLength'] + meta['partitionKeyLength'];
139
+ break;
140
+ }
141
+
142
+ switch (rt) {
143
+ case RT_RESOURCE_MAP:
144
+ case RT_JSON_PARTITIONED:
145
+ case RT_BINARY_PARTITIONED:
146
+ for (let keyStr of acc.listInputFields()) {
147
+ if (rt === RT_BINARY_PARTITIONED) {
148
+ const k = removeIndexSuffix(keyStr);
149
+ if (!k) continue;
150
+ else keyStr = k;
151
+ }
152
+ const key = [...JSON.parse(keyStr)] as PColumnKey;
153
+ data.push(key);
154
+ }
155
+
156
+ break;
157
+
158
+ case RT_RESOURCE_MAP_PARTITIONED:
159
+ case RT_BINARY_SUPER_PARTITIONED:
160
+ case RT_JSON_SUPER_PARTITIONED:
161
+ for (const supKeyStr of acc.listInputFields()) {
162
+ const keyPrefix = [...JSON.parse(supKeyStr)] as PColumnKey;
163
+
164
+ const value = acc.resolve({ field: supKeyStr, assertFieldType: 'Input' });
165
+ if (value !== undefined) {
166
+ for (let keyStr of value.listInputFields()) {
167
+ if (rt === RT_BINARY_SUPER_PARTITIONED) {
168
+ const k = removeIndexSuffix(keyStr);
169
+ if (!k) continue;
170
+ else keyStr = k;
171
+ }
172
+ const key = [...keyPrefix, ...JSON.parse(keyStr)] as PColumnKey;
173
+ data.push(key);
174
+ }
175
+ }
176
+ }
177
+ break;
178
+ }
179
+
180
+ return { data, keyLength };
181
+ }
182
+
183
+ /** Returns an array of unique partition keys for each column: the i-th element in the resulting 2d array contains all unique values of i-th partition axis. */
184
+ // @TODO define a class with various resource map operations
185
+ export function getUniquePartitionKeys(
186
+ acc: TreeNodeAccessor | undefined
187
+ ): (string | number)[][] | undefined {
188
+ const list = getPartitionKeysList(acc);
189
+ if (!list) return undefined;
190
+
191
+ const { data, keyLength } = list;
192
+
193
+ const result: Set<string | number>[] = [];
194
+
195
+ for (let i = 0; i < keyLength; ++i) {
196
+ result.push(new Set());
197
+ }
198
+
199
+ for (const l of data) {
200
+ if (l.length !== keyLength) {
201
+ throw new Error('key length does not match partition length');
202
+ }
203
+ for (let i = 0; i < keyLength; ++i) {
204
+ result[i].add(l[i]);
205
+ }
206
+ }
207
+
208
+ return result.map((s) => Array.from(s.values()));
209
+ }