@peerbit/indexer-sqlite3 2.0.2-e209d2e → 2.1.0-369b236

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/src/schema.ts CHANGED
@@ -162,6 +162,85 @@ type SQLField = {
162
162
  describesExistenceOfAnother?: string;
163
163
  };
164
164
  type SQLConstraint = { name: string; definition: string };
165
+ type PrimaryFieldInfo = Pick<
166
+ SQLField,
167
+ "name" | "type" | "from" | "unwrappedType"
168
+ >;
169
+
170
+ const createScalarSQLField = (
171
+ path: string[],
172
+ field: Field,
173
+ type: FieldType,
174
+ primary: string | false,
175
+ isOptional: boolean,
176
+ ): SQLField => {
177
+ const name = getInlineTableFieldName(path.slice(1), field.key);
178
+ const isPrimary = primary !== false && name === primary;
179
+ const sqlType = toSQLType(type, isOptional);
180
+ return {
181
+ name,
182
+ key: field.key,
183
+ definition: `${escapeColumnName(name)} ${sqlType} ${isPrimary ? "PRIMARY KEY" : ""}`,
184
+ type: sqlType,
185
+ isPrimary,
186
+ from: field,
187
+ unwrappedType: unwrapNestedType(field.type),
188
+ path: [...path.slice(1), field.key],
189
+ };
190
+ };
191
+
192
+ const resolvePrimaryFieldInfoFromSchema = (
193
+ ctor: Constructor<any>,
194
+ path: string[],
195
+ primary: string,
196
+ ): PrimaryFieldInfo | undefined => {
197
+ const schema = getSchema(ctor);
198
+ if (!schema) {
199
+ return undefined;
200
+ }
201
+
202
+ for (const field of schema.fields) {
203
+ let fieldType: FieldType = field.type;
204
+
205
+ // option(T) is stored as T (nullable) in SQL.
206
+ if (fieldType instanceof OptionKind) {
207
+ fieldType = fieldType.elementType;
208
+ }
209
+
210
+ fieldType = unwrapNestedType(fieldType);
211
+
212
+ // Arrays are always stored in separate tables.
213
+ if (fieldType instanceof VecKind) {
214
+ continue;
215
+ }
216
+
217
+ if (typeof fieldType === "string" || isUint8ArrayType(fieldType)) {
218
+ const sqlField = createScalarSQLField(path, field, fieldType, primary, true);
219
+ if (sqlField.isPrimary) {
220
+ return {
221
+ name: sqlField.name,
222
+ type: sqlField.type,
223
+ from: sqlField.from,
224
+ unwrappedType: sqlField.unwrappedType,
225
+ };
226
+ }
227
+ } else if (
228
+ typeof fieldType === "function" &&
229
+ clazzCanBeInlined(fieldType as Constructor<any>)
230
+ ) {
231
+ const nested = resolvePrimaryFieldInfoFromSchema(
232
+ fieldType as Constructor<any>,
233
+ [...path, field.key],
234
+ primary,
235
+ );
236
+ if (nested) {
237
+ return nested;
238
+ }
239
+ }
240
+ }
241
+
242
+ return undefined;
243
+ };
165
244
 
166
245
  export interface Table {
167
246
  name: string;
@@ -331,21 +410,30 @@ export const getSQLFields = (
331
410
 
332
411
  let foundPrimary = false;
333
412
 
413
+ // Resolve the primary field info independent of schema field order. This is
414
+ // needed because nested table generation can happen before the primary field
415
+ // has been processed and added to `sqlFields`.
416
+ const parentPrimaryFieldInfo: PrimaryFieldInfo =
417
+ primary === false || primary === CHILD_TABLE_ID
418
+ ? {
419
+ name: CHILD_TABLE_ID,
420
+ type: "INTEGER",
421
+ from: undefined,
422
+ unwrappedType: undefined,
423
+ }
424
+ : resolvePrimaryFieldInfoFromSchema(ctor, path, primary) || {
425
+ // Fallback: nested tables use synthetic integer ids, and we allow that
426
+ // primary to be unresolved here.
427
+ name: primary,
428
+ type: "INTEGER",
429
+ from: undefined,
430
+ unwrappedType: undefined,
431
+ };
432
+
334
433
  const addJoinFields =
335
434
  primary === false
336
435
  ? addJoinFieldFromParent
337
436
  : (fields: SQLField[], contstraints: SQLConstraint[]) => {
338
- // we resolve primary field here since it might be unknown until this point
339
- const parentPrimaryField =
340
- primary != null
341
- ? sqlFields.find((field) => field.name === primary)
342
- : undefined;
343
- const parentPrimaryFieldName =
344
- parentPrimaryField?.name || CHILD_TABLE_ID;
345
- const parentPrimaryFieldType = parentPrimaryField
346
- ? parentPrimaryField.type
347
- : "INTEGER";
348
-
349
437
  fields.unshift(
350
438
  {
351
439
  name: CHILD_TABLE_ID,
@@ -362,17 +450,17 @@ export const getSQLFields = (
362
450
  {
363
451
  name: PARENT_TABLE_ID,
364
452
  key: PARENT_TABLE_ID,
365
- definition: `${PARENT_TABLE_ID} ${parentPrimaryFieldType}`,
366
- type: parentPrimaryFieldType,
367
- from: parentPrimaryField?.from,
368
- unwrappedType: parentPrimaryField?.unwrappedType,
453
+ definition: `${PARENT_TABLE_ID} ${parentPrimaryFieldInfo.type}`,
454
+ type: parentPrimaryFieldInfo.type,
455
+ from: parentPrimaryFieldInfo.from,
456
+ unwrappedType: parentPrimaryFieldInfo.unwrappedType,
369
457
  isPrimary: false,
370
458
  path: [PARENT_TABLE_ID],
371
459
  },
372
460
  );
373
461
  contstraints.push({
374
462
  name: `${PARENT_TABLE_ID}_fk`,
375
- definition: `CONSTRAINT ${PARENT_TABLE_ID}_fk FOREIGN KEY(${PARENT_TABLE_ID}) REFERENCES ${tableName}(${parentPrimaryFieldName}) ON DELETE CASCADE`,
463
+ definition: `CONSTRAINT ${PARENT_TABLE_ID}_fk FOREIGN KEY(${PARENT_TABLE_ID}) REFERENCES ${tableName}(${parentPrimaryFieldInfo.name}) ON DELETE CASCADE`,
376
464
  });
377
465
  };
378
466
 
@@ -446,27 +534,13 @@ export const getSQLFields = (
446
534
  };
447
535
 
448
536
  const handleSimpleField = (
449
- key: string,
450
537
  field: Field,
451
538
  type: FieldType,
452
539
  isOptional: boolean,
453
540
  ) => {
454
- let keyString = getInlineTableFieldName(path.slice(1), key);
455
-
456
- const isPrimary = primary != null && keyString === primary;
457
- foundPrimary = foundPrimary || isPrimary;
458
-
459
- const fieldType = toSQLType(type, isOptional);
460
- sqlFields.push({
461
- name: keyString,
462
- key,
463
- definition: `${escapeColumnName(keyString)} ${fieldType} ${isPrimary ? "PRIMARY KEY" : ""}`,
464
- type: fieldType,
465
- isPrimary,
466
- from: field,
467
- unwrappedType: unwrapNestedType(field.type),
468
- path: [...path.slice(1), key],
469
- });
541
+ const sqlField = createScalarSQLField(path, field, type, primary, isOptional);
542
+ foundPrimary = foundPrimary || sqlField.isPrimary;
543
+ sqlFields.push(sqlField);
470
544
  };
471
545
 
472
546
  const handleField = (
@@ -480,7 +554,7 @@ export const getSQLFields = (
480
554
  }
481
555
 
482
556
  if (typeof type === "string" || type === Uint8Array) {
483
- handleSimpleField(key, field, type, true);
557
+ handleSimpleField(field, type, true);
484
558
  } else if (
485
559
  typeof type === "function" &&
486
560
  clazzCanBeInlined(type as Constructor<any>)