Skip to content

Commit 0390b85

Browse files
committed
Fix broken inverse FK input types when keys based on same column names. Closes mlipscombe#28
1 parent cc93219 commit 0390b85

File tree

3 files changed

+307
-4
lines changed

3 files changed

+307
-4
lines changed

__tests__/integration/__snapshots__/create.test.js.snap

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,200 @@ GraphQLSchema {
13231323
}
13241324
`;
13251325

1326+
exports[`reverse nested mutation with non-serial / default parent PK creates record 1`] = `
1327+
GraphQLSchema {
1328+
"__validationErrors": Array [],
1329+
"_directives": Array [
1330+
"@include",
1331+
"@skip",
1332+
"@deprecated",
1333+
"@specifiedBy",
1334+
],
1335+
"_implementationsMap": Object {
1336+
"Node": Object {
1337+
"interfaces": Array [],
1338+
"objects": Array [
1339+
"Query",
1340+
"Child",
1341+
"Parent",
1342+
],
1343+
},
1344+
},
1345+
"_mutationType": "Mutation",
1346+
"_queryType": "Query",
1347+
"_subTypeMap": Object {},
1348+
"_subscriptionType": undefined,
1349+
"_typeMap": Object {
1350+
"Boolean": "Boolean",
1351+
"Child": "Child",
1352+
"ChildChildPkeyConnect": "ChildChildPkeyConnect",
1353+
"ChildChildPkeyDelete": "ChildChildPkeyDelete",
1354+
"ChildCondition": "ChildCondition",
1355+
"ChildInput": "ChildInput",
1356+
"ChildNodeIdConnect": "ChildNodeIdConnect",
1357+
"ChildNodeIdDelete": "ChildNodeIdDelete",
1358+
"ChildOnChildForChildParentFkeyNodeIdUpdate": "ChildOnChildForChildParentFkeyNodeIdUpdate",
1359+
"ChildOnChildForChildParentFkeyUsingChildPkeyUpdate": "ChildOnChildForChildParentFkeyUsingChildPkeyUpdate",
1360+
"ChildParentFkeyChildCreateInput": "ChildParentFkeyChildCreateInput",
1361+
"ChildParentFkeyInput": "ChildParentFkeyInput",
1362+
"ChildParentFkeyInverseInput": "ChildParentFkeyInverseInput",
1363+
"ChildParentFkeyParentCreateInput": "ChildParentFkeyParentCreateInput",
1364+
"ChildPatch": "ChildPatch",
1365+
"ChildrenConnection": "ChildrenConnection",
1366+
"ChildrenEdge": "ChildrenEdge",
1367+
"ChildrenOrderBy": "ChildrenOrderBy",
1368+
"CreateChildInput": "CreateChildInput",
1369+
"CreateChildPayload": "CreateChildPayload",
1370+
"CreateParentInput": "CreateParentInput",
1371+
"CreateParentPayload": "CreateParentPayload",
1372+
"Cursor": "Cursor",
1373+
"DeleteChildByIdInput": "DeleteChildByIdInput",
1374+
"DeleteChildInput": "DeleteChildInput",
1375+
"DeleteChildPayload": "DeleteChildPayload",
1376+
"DeleteParentByIdInput": "DeleteParentByIdInput",
1377+
"DeleteParentInput": "DeleteParentInput",
1378+
"DeleteParentPayload": "DeleteParentPayload",
1379+
"ID": "ID",
1380+
"Int": "Int",
1381+
"Mutation": "Mutation",
1382+
"Node": "Node",
1383+
"PageInfo": "PageInfo",
1384+
"Parent": "Parent",
1385+
"ParentCondition": "ParentCondition",
1386+
"ParentInput": "ParentInput",
1387+
"ParentNodeIdConnect": "ParentNodeIdConnect",
1388+
"ParentNodeIdDelete": "ParentNodeIdDelete",
1389+
"ParentOnChildForChildParentFkeyNodeIdUpdate": "ParentOnChildForChildParentFkeyNodeIdUpdate",
1390+
"ParentOnChildForChildParentFkeyUsingParentPkeyUpdate": "ParentOnChildForChildParentFkeyUsingParentPkeyUpdate",
1391+
"ParentParentPkeyConnect": "ParentParentPkeyConnect",
1392+
"ParentParentPkeyDelete": "ParentParentPkeyDelete",
1393+
"ParentPatch": "ParentPatch",
1394+
"ParentsConnection": "ParentsConnection",
1395+
"ParentsEdge": "ParentsEdge",
1396+
"ParentsOrderBy": "ParentsOrderBy",
1397+
"Query": "Query",
1398+
"String": "String",
1399+
"UpdateChildByIdInput": "UpdateChildByIdInput",
1400+
"UpdateChildInput": "UpdateChildInput",
1401+
"UpdateChildPayload": "UpdateChildPayload",
1402+
"UpdateParentByIdInput": "UpdateParentByIdInput",
1403+
"UpdateParentInput": "UpdateParentInput",
1404+
"UpdateParentPayload": "UpdateParentPayload",
1405+
"__Directive": "__Directive",
1406+
"__DirectiveLocation": "__DirectiveLocation",
1407+
"__EnumValue": "__EnumValue",
1408+
"__Field": "__Field",
1409+
"__InputValue": "__InputValue",
1410+
"__Schema": "__Schema",
1411+
"__Type": "__Type",
1412+
"__TypeKind": "__TypeKind",
1413+
"updateChildOnChildForChildParentFkeyPatch": "updateChildOnChildForChildParentFkeyPatch",
1414+
"updateParentOnChildForChildParentFkeyPatch": "updateParentOnChildForChildParentFkeyPatch",
1415+
},
1416+
"astNode": undefined,
1417+
"description": undefined,
1418+
"extensionASTNodes": undefined,
1419+
"extensions": undefined,
1420+
}
1421+
`;
1422+
1423+
exports[`reverse nested mutation with same column names creates record 1`] = `
1424+
GraphQLSchema {
1425+
"__validationErrors": Array [],
1426+
"_directives": Array [
1427+
"@include",
1428+
"@skip",
1429+
"@deprecated",
1430+
"@specifiedBy",
1431+
],
1432+
"_implementationsMap": Object {
1433+
"Node": Object {
1434+
"interfaces": Array [],
1435+
"objects": Array [
1436+
"Query",
1437+
"Child",
1438+
"Parent",
1439+
],
1440+
},
1441+
},
1442+
"_mutationType": "Mutation",
1443+
"_queryType": "Query",
1444+
"_subTypeMap": Object {},
1445+
"_subscriptionType": undefined,
1446+
"_typeMap": Object {
1447+
"Boolean": "Boolean",
1448+
"Child": "Child",
1449+
"ChildChildPkeyConnect": "ChildChildPkeyConnect",
1450+
"ChildChildPkeyDelete": "ChildChildPkeyDelete",
1451+
"ChildCondition": "ChildCondition",
1452+
"ChildInput": "ChildInput",
1453+
"ChildNodeIdConnect": "ChildNodeIdConnect",
1454+
"ChildNodeIdDelete": "ChildNodeIdDelete",
1455+
"ChildOnChildForChildParentFkeyNodeIdUpdate": "ChildOnChildForChildParentFkeyNodeIdUpdate",
1456+
"ChildOnChildForChildParentFkeyUsingChildPkeyUpdate": "ChildOnChildForChildParentFkeyUsingChildPkeyUpdate",
1457+
"ChildParentFkeyChildCreateInput": "ChildParentFkeyChildCreateInput",
1458+
"ChildParentFkeyInput": "ChildParentFkeyInput",
1459+
"ChildParentFkeyInverseInput": "ChildParentFkeyInverseInput",
1460+
"ChildParentFkeyParentCreateInput": "ChildParentFkeyParentCreateInput",
1461+
"ChildPatch": "ChildPatch",
1462+
"ChildrenConnection": "ChildrenConnection",
1463+
"ChildrenEdge": "ChildrenEdge",
1464+
"ChildrenOrderBy": "ChildrenOrderBy",
1465+
"CreateChildInput": "CreateChildInput",
1466+
"CreateChildPayload": "CreateChildPayload",
1467+
"CreateParentInput": "CreateParentInput",
1468+
"CreateParentPayload": "CreateParentPayload",
1469+
"Cursor": "Cursor",
1470+
"DeleteChildByIdInput": "DeleteChildByIdInput",
1471+
"DeleteChildInput": "DeleteChildInput",
1472+
"DeleteChildPayload": "DeleteChildPayload",
1473+
"DeleteParentByParentIdInput": "DeleteParentByParentIdInput",
1474+
"DeleteParentInput": "DeleteParentInput",
1475+
"DeleteParentPayload": "DeleteParentPayload",
1476+
"ID": "ID",
1477+
"Int": "Int",
1478+
"Mutation": "Mutation",
1479+
"Node": "Node",
1480+
"PageInfo": "PageInfo",
1481+
"Parent": "Parent",
1482+
"ParentCondition": "ParentCondition",
1483+
"ParentInput": "ParentInput",
1484+
"ParentNodeIdConnect": "ParentNodeIdConnect",
1485+
"ParentNodeIdDelete": "ParentNodeIdDelete",
1486+
"ParentOnChildForChildParentFkeyNodeIdUpdate": "ParentOnChildForChildParentFkeyNodeIdUpdate",
1487+
"ParentOnChildForChildParentFkeyUsingParentPkeyUpdate": "ParentOnChildForChildParentFkeyUsingParentPkeyUpdate",
1488+
"ParentParentPkeyConnect": "ParentParentPkeyConnect",
1489+
"ParentParentPkeyDelete": "ParentParentPkeyDelete",
1490+
"ParentPatch": "ParentPatch",
1491+
"ParentsConnection": "ParentsConnection",
1492+
"ParentsEdge": "ParentsEdge",
1493+
"ParentsOrderBy": "ParentsOrderBy",
1494+
"Query": "Query",
1495+
"String": "String",
1496+
"UpdateChildByIdInput": "UpdateChildByIdInput",
1497+
"UpdateChildInput": "UpdateChildInput",
1498+
"UpdateChildPayload": "UpdateChildPayload",
1499+
"UpdateParentByParentIdInput": "UpdateParentByParentIdInput",
1500+
"UpdateParentInput": "UpdateParentInput",
1501+
"UpdateParentPayload": "UpdateParentPayload",
1502+
"__Directive": "__Directive",
1503+
"__DirectiveLocation": "__DirectiveLocation",
1504+
"__EnumValue": "__EnumValue",
1505+
"__Field": "__Field",
1506+
"__InputValue": "__InputValue",
1507+
"__Schema": "__Schema",
1508+
"__Type": "__Type",
1509+
"__TypeKind": "__TypeKind",
1510+
"updateChildOnChildForChildParentFkeyPatch": "updateChildOnChildForChildParentFkeyPatch",
1511+
"updateParentOnChildForChildParentFkeyPatch": "updateParentOnChildForChildParentFkeyPatch",
1512+
},
1513+
"astNode": undefined,
1514+
"description": undefined,
1515+
"extensionASTNodes": undefined,
1516+
"extensions": undefined,
1517+
}
1518+
`;
1519+
13261520
exports[`table with no relations is not affected by plugin 1`] = `
13271521
GraphQLSchema {
13281522
"__validationErrors": Array [],

__tests__/integration/create.test.js

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,3 +977,116 @@ test(
977977
},
978978
}),
979979
);
980+
981+
test(
982+
'reverse nested mutation with non-serial / default parent PK creates record',
983+
withSchema({
984+
setup: `
985+
create table p.parent (
986+
id text primary key,
987+
name text not null
988+
);
989+
990+
create table p.child (
991+
id serial primary key,
992+
parent_id text,
993+
name text not null,
994+
constraint child_parent_fkey foreign key (parent_id)
995+
references p.parent (id)
996+
);
997+
`,
998+
test: async ({ schema, pgClient }) => {
999+
const query = `
1000+
mutation {
1001+
createChild(
1002+
input: {
1003+
child: {
1004+
name: "test f1"
1005+
parentId: "123"
1006+
parentToParentId: {
1007+
create: {
1008+
id: "123"
1009+
name: "parent of f1"
1010+
}
1011+
}
1012+
}
1013+
}
1014+
) {
1015+
child {
1016+
id
1017+
name
1018+
parentId
1019+
parentByParentId {
1020+
id
1021+
name
1022+
}
1023+
}
1024+
}
1025+
}
1026+
`;
1027+
expect(schema).toMatchSnapshot();
1028+
1029+
const result = await graphql(schema, query, null, { pgClient });
1030+
expect(result).not.toHaveProperty('errors');
1031+
1032+
const data = result.data.createChild.child;
1033+
expect(data.parentByParentId.id).toEqual(data.parentId);
1034+
},
1035+
}),
1036+
);
1037+
1038+
test(
1039+
'reverse nested mutation with same column names creates record',
1040+
withSchema({
1041+
setup: `
1042+
create table p.parent (
1043+
parent_id text primary key,
1044+
name text not null
1045+
);
1046+
1047+
create table p.child (
1048+
id serial primary key,
1049+
parent_id text,
1050+
name text not null,
1051+
constraint child_parent_fkey foreign key (parent_id)
1052+
references p.parent (parent_id)
1053+
);
1054+
`,
1055+
test: async ({ schema, pgClient }) => {
1056+
const query = `
1057+
mutation {
1058+
createChild(
1059+
input: {
1060+
child: {
1061+
name: "test f1"
1062+
parentToParentId: {
1063+
create: {
1064+
parentId: "123"
1065+
name: "parent of f1"
1066+
}
1067+
}
1068+
}
1069+
}
1070+
) {
1071+
child {
1072+
id
1073+
name
1074+
parentId
1075+
parentByParentId {
1076+
parentId
1077+
name
1078+
}
1079+
}
1080+
}
1081+
}
1082+
`;
1083+
expect(schema).toMatchSnapshot();
1084+
1085+
const result = await graphql(schema, query, null, { pgClient });
1086+
expect(result).not.toHaveProperty('errors');
1087+
1088+
const data = result.data.createChild.child;
1089+
expect(data.parentByParentId.parentId).toEqual(data.parentId);
1090+
},
1091+
}),
1092+
);

src/PostgraphileNestedTypesPlugin.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -311,11 +311,7 @@ module.exports = function PostGraphileNestedTypesPlugin(
311311
description: `The \`${foreignTableName}\` to be created by this mutation.`,
312312
fields: () => {
313313
const inputFields = gqlForeignTableType._fields;
314-
const omittedFields = constraint.keyAttributes.map((k) =>
315-
inflection.column(k),
316-
);
317314
return Object.keys(inputFields)
318-
.filter((key) => !omittedFields.includes(key))
319315
.map((k) => Object.assign({}, { [k]: inputFields[k] }))
320316
.reduce((res, o) => Object.assign(res, o), {});
321317
},

0 commit comments

Comments
 (0)