From eba4a24c4e81f21efc14f23f67a26fb116b7508c Mon Sep 17 00:00:00 2001 From: David McAfee Date: Fri, 18 Nov 2022 11:53:24 -0800 Subject: [PATCH 1/6] fix(datastore): optional hasOne #10685 --- packages/datastore/src/storage/adapter/IndexedDBAdapter.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/datastore/src/storage/adapter/IndexedDBAdapter.ts b/packages/datastore/src/storage/adapter/IndexedDBAdapter.ts index 9a8acf1219e..49b9d9985ed 100644 --- a/packages/datastore/src/storage/adapter/IndexedDBAdapter.ts +++ b/packages/datastore/src/storage/adapter/IndexedDBAdapter.ts @@ -887,6 +887,7 @@ class IndexedDBAdapter implements Adapter { if (targetName && targetName in model) { index = hasOneIndex; const value = model[targetName]; + if (value === null) break; values = [value]; } else { // backwards compatability for older versions of codegen that did not emit targetName for HAS_ONE relations From 4758f604b4975229bbd9d62c0403511f55bffa15 Mon Sep 17 00:00:00 2001 From: Dane Pilcher Date: Fri, 18 Nov 2022 13:35:12 -0700 Subject: [PATCH 2/6] test: wip new tests --- .../datastore/__tests__/commonAdapterTests.ts | 54 +++++++- packages/datastore/__tests__/helpers.ts | 131 +++++++++++++++++- 2 files changed, 178 insertions(+), 7 deletions(-) diff --git a/packages/datastore/__tests__/commonAdapterTests.ts b/packages/datastore/__tests__/commonAdapterTests.ts index 1da20ebb62c..d3e6812dfbb 100644 --- a/packages/datastore/__tests__/commonAdapterTests.ts +++ b/packages/datastore/__tests__/commonAdapterTests.ts @@ -24,6 +24,8 @@ import { CompositePKParent, HasOneParent, HasOneChild, + DefaultPKHasOneParent, + DefaultPKHasOneChild, } from './helpers'; export { pause }; @@ -370,14 +372,25 @@ export function addCommonQueryTests({ let Post: PersistentModelConstructor; let HasOneParent: PersistentModelConstructor; let HasOneChild: PersistentModelConstructor; + let DefaultPKHasOneParent: PersistentModelConstructor; + let DefaultPKHasOneChild: PersistentModelConstructor; beforeEach(async () => { const classes = initSchema(testSchema()); - ({ Comment, Post, HasOneParent, HasOneChild } = classes as { + ({ + Comment, + Post, + HasOneParent, + HasOneChild, + DefaultPKHasOneParent, + DefaultPKHasOneChild, + } = classes as { Comment: PersistentModelConstructor; Post: PersistentModelConstructor; HasOneParent: PersistentModelConstructor; HasOneChild: PersistentModelConstructor; + DefaultPKHasOneParent: PersistentModelConstructor; + DefaultPKHasOneChild: PersistentModelConstructor; }); }); @@ -517,7 +530,7 @@ export function addCommonQueryTests({ }); (isSQLiteAdapter() ? test.skip : test)( - 'deleting disconnected hasOne', + 'deleting disconnected hasOne with cpk', async () => { const hasOneParent = await DataStore.save(new HasOneParent({})); @@ -530,7 +543,7 @@ export function addCommonQueryTests({ ); (isSQLiteAdapter() ? test.skip : test)( - 'deleting connected hasOne', + 'deleting connected hasOne with cpk', async () => { const hasOneChild = await DataStore.save(new HasOneChild({})); const hasOneParent = await DataStore.save( @@ -548,6 +561,41 @@ export function addCommonQueryTests({ ).toBeUndefined(); } ); + + (isSQLiteAdapter() ? test.skip : test)( + 'deleting disconnected hasOne without cpk', + async () => { + const hasOneParent = await DataStore.save( + new DefaultPKHasOneParent({}) + ); + + await DataStore.delete(hasOneParent); + + expect( + await DataStore.query(DefaultPKHasOneParent, hasOneParent.id) + ).toBeUndefined(); + } + ); + + (isSQLiteAdapter() ? test.skip : test)( + 'deleting connected hasOne without cpk', + async () => { + const hasOneChild = await DataStore.save(new DefaultPKHasOneChild({})); + const hasOneParent = await DataStore.save( + new DefaultPKHasOneParent({ child: hasOneChild }) + ); + + await DataStore.delete(hasOneParent); + + expect( + await DataStore.query(DefaultPKHasOneParent, hasOneParent.id) + ).toBeUndefined(); + + expect( + await DataStore.query(DefaultPKHasOneChild, hasOneChild.id) + ).toBeUndefined(); + } + ); }); describe('Related models', () => { diff --git a/packages/datastore/__tests__/helpers.ts b/packages/datastore/__tests__/helpers.ts index b5efa455e96..db0a230addb 100644 --- a/packages/datastore/__tests__/helpers.ts +++ b/packages/datastore/__tests__/helpers.ts @@ -996,6 +996,8 @@ export function getDataStore({ online = false, isNode = true } = {}) { DefaultPKChild, HasOneParent, HasOneChild, + DefaultPKHasOneParent, + DefaultPKHasOneChild, } = classes as { ModelWithBoolean: PersistentModelConstructor; Post: PersistentModelConstructor; @@ -1010,6 +1012,8 @@ export function getDataStore({ online = false, isNode = true } = {}) { DefaultPKChild: PersistentModelConstructor; HasOneParent: PersistentModelConstructor; HasOneChild: PersistentModelConstructor; + DefaultPKHasOneParent: PersistentModelConstructor; + DefaultPKHasOneChild: PersistentModelConstructor; }; return { @@ -1031,6 +1035,8 @@ export function getDataStore({ online = false, isNode = true } = {}) { DefaultPKChild, HasOneParent, HasOneChild, + DefaultPKHasOneParent, + DefaultPKHasOneChild, }; } @@ -1294,10 +1300,6 @@ export declare class DefaultPKParent { } export declare class DefaultPKChild { - readonly [__modelMeta__]: { - identifier: OptionallyManagedIdentifier; - readOnlyFields: 'createdAt' | 'updatedAt'; - }; readonly id: string; readonly content?: string | null; readonly parent: Promise; @@ -1313,6 +1315,34 @@ export declare class DefaultPKChild { ): DefaultPKChild; } +export declare class DefaultPKHasOneParent { + readonly id: string; + readonly child?: Promise; + readonly createdAt?: string | null; + readonly updatedAt?: string | null; + constructor(init: ModelInit); + static copyOf( + source: DefaultPKHasOneParent, + mutator: ( + draft: MutableModel + ) => MutableModel | void + ): DefaultPKHasOneParent; +} + +export declare class DefaultPKHasOneChild { + readonly id: string; + readonly createdAt?: string | null; + readonly updatedAt?: string | null; + readonly defaultPKHasOneParentChildrenId?: string | null; + constructor(init: ModelInit); + static copyOf( + source: DefaultPKHasOneChild, + mutator: ( + draft: MutableModel + ) => MutableModel | void + ): DefaultPKHasOneChild; +} + /** * This is it. */ @@ -2335,6 +2365,99 @@ export function testSchema(): Schema { }, ], }, + DefaultPKHasOneParent: { + name: 'DefaultPKHasOneParent', + fields: { + id: { + name: 'id', + isArray: false, + type: 'ID', + isRequired: true, + attributes: [], + }, + child: { + name: 'child', + isArray: false, + type: { + model: 'DefaultPKHasOneChild', + }, + isRequired: false, + attributes: [], + association: { + connectionType: 'HAS_ONE', + associatedWith: 'id', + targetName: 'defaultPKHasOneParentChildId', + }, + }, + createdAt: { + name: 'createdAt', + isArray: false, + type: 'AWSDateTime', + isRequired: false, + attributes: [], + isReadOnly: true, + }, + updatedAt: { + name: 'updatedAt', + isArray: false, + type: 'AWSDateTime', + isRequired: false, + attributes: [], + isReadOnly: true, + }, + defaultPKHasOneParentChildId: { + name: 'defaultPKHasOneParentChildId', + isArray: false, + type: 'ID', + isRequired: false, + attributes: [], + }, + }, + syncable: true, + pluralName: 'DefaultPKHasOneParents', + attributes: [ + { + type: 'model', + properties: {}, + }, + ], + }, + DefaultPKHasOneChild: { + name: 'DefaultPKHasOneChild', + fields: { + id: { + name: 'id', + isArray: false, + type: 'ID', + isRequired: true, + attributes: [], + }, + createdAt: { + name: 'createdAt', + isArray: false, + type: 'AWSDateTime', + isRequired: false, + attributes: [], + isReadOnly: true, + }, + updatedAt: { + name: 'updatedAt', + isArray: false, + type: 'AWSDateTime', + isRequired: false, + attributes: [], + isReadOnly: true, + }, + }, + syncable: true, + pluralName: 'DefaultPKHasOneChildren', + attributes: [ + { + type: 'model', + properties: {}, + }, + ], + }, CompositePKParent: { name: 'CompositePKParent', fields: { From 2e80d53fb1302e1d0d691af9c2c24499cbc82011 Mon Sep 17 00:00:00 2001 From: Dane Pilcher Date: Fri, 18 Nov 2022 13:43:50 -0700 Subject: [PATCH 3/6] test: restore metadata --- packages/datastore/__tests__/helpers.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/datastore/__tests__/helpers.ts b/packages/datastore/__tests__/helpers.ts index db0a230addb..403335a08f8 100644 --- a/packages/datastore/__tests__/helpers.ts +++ b/packages/datastore/__tests__/helpers.ts @@ -1300,6 +1300,10 @@ export declare class DefaultPKParent { } export declare class DefaultPKChild { + readonly [__modelMeta__]: { + identifier: OptionallyManagedIdentifier; + readOnlyFields: 'createdAt' | 'updatedAt'; + }; readonly id: string; readonly content?: string | null; readonly parent: Promise; From 971dd8fbe5502f906a910c381f14e82205db6156 Mon Sep 17 00:00:00 2001 From: Dane Pilcher Date: Fri, 18 Nov 2022 13:44:59 -0700 Subject: [PATCH 4/6] test: run tests on sqlite --- .../datastore/__tests__/commonAdapterTests.ts | 48 ++++++++----------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/packages/datastore/__tests__/commonAdapterTests.ts b/packages/datastore/__tests__/commonAdapterTests.ts index d3e6812dfbb..85bdde65b6e 100644 --- a/packages/datastore/__tests__/commonAdapterTests.ts +++ b/packages/datastore/__tests__/commonAdapterTests.ts @@ -562,40 +562,32 @@ export function addCommonQueryTests({ } ); - (isSQLiteAdapter() ? test.skip : test)( - 'deleting disconnected hasOne without cpk', - async () => { - const hasOneParent = await DataStore.save( - new DefaultPKHasOneParent({}) - ); + test('deleting disconnected hasOne without cpk', async () => { + const hasOneParent = await DataStore.save(new DefaultPKHasOneParent({})); - await DataStore.delete(hasOneParent); + await DataStore.delete(hasOneParent); - expect( - await DataStore.query(DefaultPKHasOneParent, hasOneParent.id) - ).toBeUndefined(); - } - ); + expect( + await DataStore.query(DefaultPKHasOneParent, hasOneParent.id) + ).toBeUndefined(); + }); - (isSQLiteAdapter() ? test.skip : test)( - 'deleting connected hasOne without cpk', - async () => { - const hasOneChild = await DataStore.save(new DefaultPKHasOneChild({})); - const hasOneParent = await DataStore.save( - new DefaultPKHasOneParent({ child: hasOneChild }) - ); + test('deleting connected hasOne without cpk', async () => { + const hasOneChild = await DataStore.save(new DefaultPKHasOneChild({})); + const hasOneParent = await DataStore.save( + new DefaultPKHasOneParent({ child: hasOneChild }) + ); - await DataStore.delete(hasOneParent); + await DataStore.delete(hasOneParent); - expect( - await DataStore.query(DefaultPKHasOneParent, hasOneParent.id) - ).toBeUndefined(); + expect( + await DataStore.query(DefaultPKHasOneParent, hasOneParent.id) + ).toBeUndefined(); - expect( - await DataStore.query(DefaultPKHasOneChild, hasOneChild.id) - ).toBeUndefined(); - } - ); + expect( + await DataStore.query(DefaultPKHasOneChild, hasOneChild.id) + ).toBeUndefined(); + }); }); describe('Related models', () => { From 47e224495866811a65fc26471f375b733b94125a Mon Sep 17 00:00:00 2001 From: Dane Pilcher Date: Fri, 18 Nov 2022 13:51:17 -0700 Subject: [PATCH 5/6] test: add content to schema --- packages/datastore/__tests__/helpers.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/datastore/__tests__/helpers.ts b/packages/datastore/__tests__/helpers.ts index 403335a08f8..45ece342cc8 100644 --- a/packages/datastore/__tests__/helpers.ts +++ b/packages/datastore/__tests__/helpers.ts @@ -1321,6 +1321,7 @@ export declare class DefaultPKChild { export declare class DefaultPKHasOneParent { readonly id: string; + readonly content?: string | null; readonly child?: Promise; readonly createdAt?: string | null; readonly updatedAt?: string | null; @@ -1335,6 +1336,7 @@ export declare class DefaultPKHasOneParent { export declare class DefaultPKHasOneChild { readonly id: string; + readonly content?: string | null; readonly createdAt?: string | null; readonly updatedAt?: string | null; readonly defaultPKHasOneParentChildrenId?: string | null; @@ -2379,6 +2381,13 @@ export function testSchema(): Schema { isRequired: true, attributes: [], }, + content: { + name: 'content', + isArray: false, + type: 'String', + isRequired: false, + attributes: [], + }, child: { name: 'child', isArray: false, @@ -2436,6 +2445,13 @@ export function testSchema(): Schema { isRequired: true, attributes: [], }, + content: { + name: 'content', + isArray: false, + type: 'String', + isRequired: false, + attributes: [], + }, createdAt: { name: 'createdAt', isArray: false, From 1c25ed12c068bf4f570c03c73d7eff0a94dd9ea3 Mon Sep 17 00:00:00 2001 From: Dane Pilcher Date: Fri, 18 Nov 2022 14:27:51 -0700 Subject: [PATCH 6/6] test: disable on sqlite --- .../datastore/__tests__/commonAdapterTests.ts | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/packages/datastore/__tests__/commonAdapterTests.ts b/packages/datastore/__tests__/commonAdapterTests.ts index 85bdde65b6e..d3e6812dfbb 100644 --- a/packages/datastore/__tests__/commonAdapterTests.ts +++ b/packages/datastore/__tests__/commonAdapterTests.ts @@ -562,32 +562,40 @@ export function addCommonQueryTests({ } ); - test('deleting disconnected hasOne without cpk', async () => { - const hasOneParent = await DataStore.save(new DefaultPKHasOneParent({})); + (isSQLiteAdapter() ? test.skip : test)( + 'deleting disconnected hasOne without cpk', + async () => { + const hasOneParent = await DataStore.save( + new DefaultPKHasOneParent({}) + ); - await DataStore.delete(hasOneParent); + await DataStore.delete(hasOneParent); - expect( - await DataStore.query(DefaultPKHasOneParent, hasOneParent.id) - ).toBeUndefined(); - }); + expect( + await DataStore.query(DefaultPKHasOneParent, hasOneParent.id) + ).toBeUndefined(); + } + ); - test('deleting connected hasOne without cpk', async () => { - const hasOneChild = await DataStore.save(new DefaultPKHasOneChild({})); - const hasOneParent = await DataStore.save( - new DefaultPKHasOneParent({ child: hasOneChild }) - ); + (isSQLiteAdapter() ? test.skip : test)( + 'deleting connected hasOne without cpk', + async () => { + const hasOneChild = await DataStore.save(new DefaultPKHasOneChild({})); + const hasOneParent = await DataStore.save( + new DefaultPKHasOneParent({ child: hasOneChild }) + ); - await DataStore.delete(hasOneParent); + await DataStore.delete(hasOneParent); - expect( - await DataStore.query(DefaultPKHasOneParent, hasOneParent.id) - ).toBeUndefined(); + expect( + await DataStore.query(DefaultPKHasOneParent, hasOneParent.id) + ).toBeUndefined(); - expect( - await DataStore.query(DefaultPKHasOneChild, hasOneChild.id) - ).toBeUndefined(); - }); + expect( + await DataStore.query(DefaultPKHasOneChild, hasOneChild.id) + ).toBeUndefined(); + } + ); }); describe('Related models', () => {