From 983fc950def28ac913ded2733e3578e2048476f1 Mon Sep 17 00:00:00 2001 From: coeit Date: Tue, 8 Jun 2021 17:46:38 +0200 Subject: [PATCH 01/18] refactor: association types to be either: - one_to_one - one_to_many - many_to_one - many_to_many refactor: add "implementation" field to the association definition to be on of: - sql_cross_table - generic - foreignkey --- funks.js | 210 +++++++++++++++++++++------------------- views/create-models.ejs | 8 +- 2 files changed, 113 insertions(+), 105 deletions(-) diff --git a/funks.js b/funks.js index 69c059c0..1b4ad97d 100644 --- a/funks.js +++ b/funks.js @@ -694,7 +694,7 @@ getEditableAttributes = function ( ) { let editable_attributes = {}; let target_keys = parsedAssocForeignKeys.map((assoc) => { - if (assoc.reverseAssociationType) return assoc.sourceKey; + if (assoc.type === 'many_to_many' && assoc.implementation === 'foreignkey') return assoc.sourceKey; return assoc.targetKey; }); for (let attrib in attributes) { @@ -733,126 +733,134 @@ module.exports.parseAssociations = function (dataModel) { }; if (associations !== undefined) { Object.entries(associations).forEach(([name, association]) => { - let type = association.type; + + const type = association.type; + const implementation = association.implementation; + + const schema_attributes = [ + association.target, + capitalizeString(association.target), + capitalizeString(name), + ]; let holdsTheForeignKey = false; let assocThroughArray = false; - let isStandardAssociation = - association.type !== "generic_to_many" && - association.type !== "generic_to_one"; - - //push association - if (isStandardAssociation) { - //standard - associations_info.associations.push(association); - association.targetStorageType = association.targetStorageType.toLowerCase(); - associations_info.foreignKeyAssociations[name] = association.targetKey; - } else { - //generic - associations_info.genericAssociations.push(association); - } + let assoc = Object.assign({}, association); - //if(associations_type["many"].includes(association.type) ) - if (association.type === "to_many") { - //associations_info.schema_attributes["many"][name] = [ association.target, capitalizeString(association.target), capitalizeString(inflection.pluralize(association.target))]; - associations_info.schema_attributes["many"][name] = [ - association.target, - capitalizeString(association.target), - capitalizeString(name), - ]; - if (association.reverseAssociationType === "to_many") { - assocThroughArray = true; - } - //}else if(associations_type["one"].includes(association.type)) - } else if (association.type === "to_one") { - associations_info.schema_attributes["one"][name] = [ - association.target, - capitalizeString(association.target), - capitalizeString(name), - ]; - if (association.keyIn === dataModel.model) { - holdsTheForeignKey = true; - } - } else if (association.type === "to_many_through_sql_cross_table") { - if ( - association.sourceKey === undefined || - association.keysIn === undefined || - association.targetStorageType !== "sql" - ) { - console.error( - colors.red( - `ERROR: to_many_through_sql_cross_table only allowed for relational database types with well defined cross-table` - ) - ); - } - associations_info.schema_attributes["many"][name] = [ - association.target, - capitalizeString(association.target), - capitalizeString(name), - ]; - } else if (association.type === "generic_to_one") { - associations_info.schema_attributes["generic_one"][name] = [ - association.target, - capitalizeString(association.target), - capitalizeString(name), - ]; - } else if (association.type === "generic_to_many") { - associations_info.schema_attributes["generic_many"][name] = [ - association.target, - capitalizeString(association.target), - capitalizeString(name), - ]; - } else { + if (type !== 'one_to_one' && type !== 'one_to_many' && type !== 'many_to_one' && type !== 'many_to_many') { console.error( colors.red("Association type " + association.type + " not supported.") ); } - let assoc = Object.assign({}, association); - //push association - if (isStandardAssociation) { - //standard - assoc["name"] = name; - assoc["name_lc"] = uncapitalizeString(name); - assoc["name_cp"] = capitalizeString(name); - assoc["target_lc"] = uncapitalizeString(association.target); - assoc["target_lc_pl"] = inflection.pluralize( - uncapitalizeString(association.target) - ); - assoc["target_pl"] = inflection.pluralize(association.target); - assoc["target_cp"] = capitalizeString(association.target); //inflection.capitalize(association.target); - assoc["target_cp_pl"] = capitalizeString( - inflection.pluralize(association.target) - ); //inflection.capitalize(inflection.pluralize(association.target)); + // set default association fields + assoc["name"] = name; + assoc["name_lc"] = uncapitalizeString(name); + assoc["name_cp"] = capitalizeString(name); + assoc["target_lc"] = uncapitalizeString(association.target); + assoc["target_lc_pl"] = inflection.pluralize( + uncapitalizeString(association.target) + ); + assoc["target_pl"] = inflection.pluralize(association.target); + assoc["target_cp"] = capitalizeString(association.target); //inflection.capitalize(association.target); + assoc["target_cp_pl"] = capitalizeString( + inflection.pluralize(association.target) + ); + + if (implementation !== 'generic') { + // set extra association fields assoc["targetKey"] = association.targetKey; assoc["targetKey_cp"] = capitalizeString(association.targetKey); if (association.keyIn) { assoc["keyIn_lc"] = uncapitalizeString(association.keyIn); } - assoc["holdsForeignKey"] = holdsTheForeignKey; - assoc["assocThroughArray"] = assocThroughArray; + assoc["holdsForeignKey"] = false; + assoc["assocThroughArray"] = false; + + assoc.targetStorageType = association.targetStorageType.toLowerCase(); + association.targetStorageType = association.targetStorageType.toLowerCase(); + associations_info.associations.push(association); + associations_info.foreignKeyAssociations[name] = association.targetKey; } else { - //generic - assoc["name"] = name; - assoc["name_lc"] = uncapitalizeString(name); - assoc["name_cp"] = capitalizeString(name); - assoc["target_lc"] = uncapitalizeString(association.target); - assoc["target_lc_pl"] = inflection.pluralize( - uncapitalizeString(association.target) - ); - assoc["target_pl"] = inflection.pluralize(association.target); - assoc["target_cp"] = capitalizeString(association.target); //inflection.capitalize(association.target); - assoc["target_cp_pl"] = capitalizeString( - inflection.pluralize(association.target) - ); //inflection.capitalize(inflection.pluralize(association.target)); + associations_info.genericAssociations.push(association); } - associations_info[type].push(assoc); - //associations_info[type].push(assoc); + // switch implementation types + switch (implementation) { + case 'generic': + switch (type) { + case 'one_to_one': + case 'many_to_one': + associations_info.schema_attributes["generic_one"][name] = schema_attributes; + associations_info['generic_to_one'].push(assoc); + break; + case 'one_to_many': + case 'many_to_many': + associations_info.schema_attributes["generic_many"][name] = schema_attributes; + associations_info['generic_to_many'].push(assoc); + break; + default: + break; + } + break; + case 'sql_cross_table': + if (type !== 'many_to_many' + || association.sourceKey === undefined + || association.keysIn === undefined + || association.targetStorageType !== "sql" ) { + console.error( + colors.red( + `ERROR: many_to_many through crosstable only allowed for relational database types with well defined cross-table` + ) + ); + } + + associations_info.schema_attributes["many"][name] = schema_attributes; + associations_info['to_many_through_sql_cross_table'].push(assoc); + break; + case 'foreignkey': + associations_info.foreignKeyAssociations[name] = association.targetKey; + switch (type) { + case 'one_to_one': + case 'many_to_one': + // schema attrtibutes + associations_info.schema_attributes["one"][name] = schema_attributes; + // holds foreignKey ? + if (association.keyIn === dataModel.model) { + assoc["holdsForeignKey"] = true; + } + associations_info['to_one'].push(assoc); + break; + case 'many_to_many': + assoc["assocThroughArray"] = true; + case 'one_to_many': + associations_info.schema_attributes["many"][name] = schema_attributes; + associations_info['to_many'].push(assoc); + break; + default: + break; + } + break; + default: + if (implementation) { + console.error( + colors.red( + `ERROR: unallowed association implementation type ${implementation}.` + ) + ); + } else { + console.error( + colors.red( + `ERROR: Please specify an implementation type.` + ) + ); + } + } }); - } + }; associations_info.mutations_attributes = attributesToString( associations_info.mutations_attributes ); + // console.log(JSON.stringify(associations_info,null,2)); return associations_info; }; diff --git a/views/create-models.ejs b/views/create-models.ejs index d436f2c0..a1034eb5 100644 --- a/views/create-models.ejs +++ b/views/create-models.ejs @@ -113,16 +113,16 @@ module.exports = class <%- nameLc -%> extends Sequelize.Model{ <%for(let i=0; i< associationsArguments[key].length; i++){-%> <%if (key !== 'associations'){-%> <%if(associationsArguments[key][i].targetStorageType === 'sql' && !associationsArguments[key][i].assocThroughArray){-%> - <%if (associationsArguments[key][i].type === 'to_one' && associationsArguments[key][i].keyIn !== associationsArguments[key][i].target){-%> + <%if (associationsArguments[key][i].type.includes('to_one') && associationsArguments[key][i].keyIn !== associationsArguments[key][i].target){-%> <%- nameLc -%>.belongsTo(models.<%= associationsArguments[key][i].target_lc -%> <%}-%> - <% if (associationsArguments[key][i].type === 'to_one' && associationsArguments[key][i].keyIn === associationsArguments[key][i].target){-%> + <% if (associationsArguments[key][i].type.includes('to_one') && associationsArguments[key][i].keyIn === associationsArguments[key][i].target){-%> <%- nameLc -%>.hasOne(models.<%= associationsArguments[key][i].target_lc -%> <%}-%> - <% if (associationsArguments[key][i].type === 'to_many' && associationsArguments[key][i].keyIn === associationsArguments[key][i].target){-%> + <% if (associationsArguments[key][i].type === 'one_to_many' && associationsArguments[key][i].keyIn === associationsArguments[key][i].target){-%> <%- nameLc -%>.hasMany(models.<%= associationsArguments[key][i].target_lc -%> <%}-%> - <% if (associationsArguments[key][i].type === 'to_many_through_sql_cross_table' ){-%> + <% if (associationsArguments[key][i].type === 'many_to_many' && associationsArguments[key][i].implementation === 'sql_cross_table'){-%> <%- nameLc -%>.belongsToMany(models.<%= associationsArguments[key][i].target_lc -%> <%}-%> <% if(key === 'to_many_through_sql_cross_table'){ -%> ,{as: '<%= associationsArguments[key][i].name -%>', From fb64fc1257dfbbc3a34562b61cdc4a7aa6c46863 Mon Sep 17 00:00:00 2001 From: coeit Date: Tue, 8 Jun 2021 17:46:59 +0200 Subject: [PATCH 02/18] refactor: unit tests for new association types --- test/mocha_unit.test.js | 46 ++++--- test/unit_test_misc/data_models.js | 128 +++++++++++------- test/unit_test_misc/data_models_cassandra.js | 16 ++- .../unit_test_misc/data_models_distributed.js | 39 ++++-- test/unit_test_misc/data_models_extendedId.js | 12 +- test/unit_test_misc/data_models_generic.js | 24 ++-- .../data_models_generic_webservice.js | 18 ++- test/unit_test_misc/data_models_mongodb.js | 10 +- .../unit_test_misc/data_models_refactoring.js | 36 +++-- test/unit_test_misc/data_models_zendro.js | 24 ++-- .../test-describe/distributed-models.js | 15 +- .../test-describe/zendro-servers.js | 6 +- 12 files changed, 244 insertions(+), 130 deletions(-) diff --git a/test/mocha_unit.test.js b/test/mocha_unit.test.js index 1a97f822..d2e71bce 100644 --- a/test/mocha_unit.test.js +++ b/test/mocha_unit.test.js @@ -1355,7 +1355,8 @@ describe("Parse associations", function () { }, to_one: [ { - type: "to_one", + type: "many_to_one", + implementation: "foreignkey", target: "individual", targetKey: "individual_id", targetKey_cp: "Individual_id", @@ -1383,7 +1384,8 @@ describe("Parse associations", function () { }, associations: [ { - type: "to_one", + type: "many_to_one", + implementation: "foreignkey", target: "individual", targetKey: "individual_id", keyIn: "transcript_count", @@ -1413,7 +1415,8 @@ describe("Parse associations", function () { to_one: [], to_many: [ { - type: "to_many", + type: "one_to_many", + implementation: "foreignkey", target: "transcript_count", keyIn: "transcript_count", targetKey: "individual_id", @@ -1440,7 +1443,8 @@ describe("Parse associations", function () { }, associations: [ { - type: "to_many", + type: "one_to_many", + implementation: "foreignkey", target: "transcript_count", keyIn: "transcript_count", targetKey: "individual_id", @@ -1454,7 +1458,7 @@ describe("Parse associations", function () { it("03. Single to_many_through_sql_cross_table", function () { let association = models.assoc_through_project_researcher; - association.type = "to_many_through_sql_cross_table"; + // association.type = "many_to_many"; let model = { model: "Person", associations: { assoc: association } }; let res = funks.parseAssociations(model, "sql"); expect(res).to.deep.equal({ @@ -1470,7 +1474,8 @@ describe("Parse associations", function () { to_many: [], to_many_through_sql_cross_table: [ { - type: "to_many_through_sql_cross_table", + type: "many_to_many", + implementation: "sql_cross_table", target: "Project", targetKey: "projectId", targetKey_cp: "ProjectId", @@ -1497,7 +1502,8 @@ describe("Parse associations", function () { }, associations: [ { - type: "to_many_through_sql_cross_table", + type: "many_to_many", + implementation: "sql_cross_table", target: "Project", targetKey: "projectId", sourceKey: "researcherId", @@ -1518,7 +1524,7 @@ describe("Parse associations", function () { it("04. Two associations: to_many and to_many_through_sql_cross_table", function () { let person = models.person; - person.associations.books.type = "to_many_through_sql_cross_table"; + // person.associations.books.type = "to_many_through_sql_cross_table"; let res = funks.parseAssociations(person, "sql"); expect(res).to.deep.equal({ schema_attributes: { @@ -1533,7 +1539,8 @@ describe("Parse associations", function () { to_one: [], to_many: [ { - type: "to_many", + type: "one_to_many", + implementation: "foreignkey", target: "Dog", targetKey: "personId", targetKey_cp: "PersonId", @@ -1554,7 +1561,8 @@ describe("Parse associations", function () { ], to_many_through_sql_cross_table: [ { - type: "to_many_through_sql_cross_table", + type: "many_to_many", + implementation: "sql_cross_table", target: "Book", targetKey: "bookId", targetKey_cp: "BookId", @@ -1581,14 +1589,16 @@ describe("Parse associations", function () { }, associations: [ { - type: "to_many", + type: "one_to_many", + implementation: "foreignkey", target: "Dog", targetKey: "personId", keyIn: "Dog", targetStorageType: "sql", }, { - type: "to_many_through_sql_cross_table", + type: "many_to_many", + implementation: "sql_cross_table", target: "Book", targetKey: "bookId", sourceKey: "personId", @@ -1615,7 +1625,8 @@ describe("Parse associations", function () { }, to_one: [ { - type: "to_one", + type: "many_to_one", + implementation: "foreignkey", target: "Person", targetKey: "personId", targetKey_cp: "PersonId", @@ -1636,7 +1647,8 @@ describe("Parse associations", function () { assocThroughArray: false, }, { - type: "to_one", + type: "many_to_one", + implementation: "foreignkey", target: "Researcher", targetKey: "researcherId", targetKey_cp: "ResearcherId", @@ -1666,7 +1678,8 @@ describe("Parse associations", function () { }, associations: [ { - type: "to_one", + type: "many_to_one", + implementation: "foreignkey", target: "Person", targetKey: "personId", keyIn: "Dog", @@ -1675,7 +1688,8 @@ describe("Parse associations", function () { sublabel: "lastName", }, { - type: "to_one", + type: "many_to_one", + implementation: "foreignkey", target: "Researcher", targetKey: "researcherId", keyIn: "Dog", diff --git a/test/unit_test_misc/data_models.js b/test/unit_test_misc/data_models.js index 4981f8f9..e879b269 100644 --- a/test/unit_test_misc/data_models.js +++ b/test/unit_test_misc/data_models.js @@ -10,7 +10,8 @@ module.exports.transcript_count = { }, "associations":{ "individual":{ - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "individual", "targetKey" : "individual_id", "keyIn": "transcript_count", @@ -27,7 +28,8 @@ module.exports.individual = { }, "associations": { "transcript_counts": { - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "transcript_count", "keyIn": "transcript_count", "targetKey" : "individual_id", @@ -65,7 +67,8 @@ module.exports.person = { }, "associations":{ "dogs":{ - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", "keyIn": "Dog", @@ -73,7 +76,8 @@ module.exports.person = { }, "books":{ - "type" : "to_many_through_sql_cross_table", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Book", "targetKey" : "bookId", "sourceKey" : "personId", @@ -94,7 +98,8 @@ module.exports.book = { "associations":{ "people" : { - "type" : "to_many_through_sql_cross_table", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Person", "targetKey" : "personId", "sourceKey" : "bookId", @@ -102,7 +107,8 @@ module.exports.book = { "targetStorageType" : "sql" }, "publisher" : { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "Publisher", "targetKey" : "publisherId", "keyIn": "Book", @@ -121,7 +127,8 @@ module.exports.researcher = { }, "associations":{ "projects":{ - "type" : "to_many_through_sql_cross_table", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Project", "targetKey" : "projectId", "sourceKey" : "researcherId", @@ -129,7 +136,8 @@ module.exports.researcher = { "targetStorageType" : "sql" }, "dog":{ - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Dog", "targetKey": "researcherId", "keyIn": "Dog", @@ -150,7 +158,8 @@ module.exports.specie = { "associations":{ "projects" : { - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "Project", "targetKey" : "specieId", "keyIn": "Project", @@ -169,7 +178,8 @@ module.exports.dog = { "associations" : { "person" : { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "Person", "targetKey" : "personId", "keyIn": "Dog", @@ -178,7 +188,8 @@ module.exports.dog = { "sublabel": "lastName" }, "researcher":{ - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target": "Researcher", "targetKey": "researcherId", "keyIn": "Dog", @@ -189,7 +200,8 @@ module.exports.dog = { } module.exports.assoc_through_project_researcher = { - "type" : "to_many_through_sql_cross_table", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Project", "targetKey" : "projectId", "sourceKey" : "researcherId", @@ -204,7 +216,8 @@ module.exports.assoc_through_project_researcher = { } module.exports.assoc_dogs_researcher = { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target": "Researcher", "targetKey": "researcherId", "keyIn": "Dog", @@ -236,7 +249,8 @@ module.exports.inDiVIdual_camelcase = { }, "associations": { "transcriptCounts": { - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "transcriptCount", "targetKey" : "individual_id", "keyIn": "transcriptCount", @@ -259,7 +273,8 @@ module.exports.transcriptCount_camelcase = { }, "associations":{ "inDiVIdual":{ - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "inDiVIdual", "targetKey" : "individual_id", "keyIn": "transcriptCount", @@ -280,7 +295,8 @@ module.exports.transcriptCount_indiv= { }, "associations":{ "individual":{ - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "Individual", "targetKey" : "individual_id", "keyIn": "transcriptCount", @@ -302,7 +318,8 @@ module.exports.dog_owner = { "associations" : { "owner" : { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "Person", "targetKey" : "owner_id_test", "keyIn": "Dog", @@ -311,7 +328,8 @@ module.exports.dog_owner = { "sublabel": "lastName" }, "keeper":{ - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target": "Researcher", "targetKey": "keeperId", "keyIn": "Dog", @@ -332,7 +350,8 @@ module.exports.person_indices = { }, "associations":{ "dogs":{ - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", "keyIn": "Dog", @@ -341,7 +360,8 @@ module.exports.person_indices = { }, "books":{ - "type" : "to_many_through_sql_cross_table", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Book", "targetKey" : "bookId", "sourceKey" : "personId", @@ -365,7 +385,8 @@ module.exports.person_externalIds = { }, "associations":{ "dogs":{ - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", "keyIn": "Dog", @@ -374,7 +395,8 @@ module.exports.person_externalIds = { }, "books":{ - "type" : "to_many_through_sql_cross_table", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Book", "targetKey" : "bookId", "sourceKey" : "personId", @@ -398,7 +420,8 @@ module.exports.academicTeam = { }, "associations":{ "members":{ - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "Researcher", "targetKey" : "academicTeamId", "keyIn": "Researcher", @@ -421,7 +444,8 @@ module.exports.person_date = { }, "associations":{ "dogs":{ - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", "keyIn": "Dog", @@ -430,7 +454,8 @@ module.exports.person_date = { }, "patients":{ - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "Dog", "targetKey" : "doctor_Id", "keyIn": "Dog", @@ -439,7 +464,8 @@ module.exports.person_date = { }, "books":{ - "type" : "to_many_through_sql_cross_table", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Book", "targetKey" : "book_Id", "sourceKey" : "person_Id", @@ -462,7 +488,8 @@ module.exports.book_authors = { "associations":{ "Authors" : { - "type" : "to_many_through_sql_cross_table", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Person", "targetKey" : "person_Id", "sourceKey" : "book_Id", @@ -472,7 +499,8 @@ module.exports.book_authors = { "sublabel" : "email" }, "publisher" : { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "Publisher", "targetKey" : "publisherId", "keyIn" : "Book", @@ -498,7 +526,8 @@ module.exports.person_description = { }, "associations":{ "dogs":{ - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", "keyIn": "Dog", @@ -506,7 +535,8 @@ module.exports.person_description = { }, "books":{ - "type" : "to_many_through_sql_cross_table", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Book", "targetKey" : "bookId", "sourceKey" : "personId", @@ -531,7 +561,8 @@ module.exports.person_description_optional = { }, "associations":{ "dogs":{ - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", "keyIn": "Dog", @@ -539,7 +570,8 @@ module.exports.person_description_optional = { }, "books":{ - "type" : "to_many_through_sql_cross_table", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Book", "targetKey" : "bookId", "sourceKey" : "personId", @@ -560,7 +592,8 @@ module.exports.academic_Team = { }, "associations":{ "members":{ - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "Researcher", "targetKey" : "AcademicTeam_Id", "keyIn": "Researcher", @@ -581,7 +614,8 @@ module.exports.dog_one_assoc = { "associations" : { "owner" : { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "Person", "targetKey" : "personId", "keyIn" : "Dog", @@ -602,7 +636,8 @@ module.exports.person_one_assoc = { "associations" : { "unique_pet" :{ - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Dog", "targetKey": "personId", "keyIn": "Dog", @@ -623,7 +658,8 @@ module.exports.book_extendedIds = { }, "associations": { "author": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Person", "targetKey": "internalPersonId", "keyIn": "Book", @@ -648,8 +684,8 @@ module.exports.author_foreignKeyArray = { "associations":{ "books":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", + "implementation": "foreignkey", "target": "book", "targetKey": "author_ids", "sourceKey": "book_ids", @@ -675,8 +711,8 @@ module.exports.author_zendro_remote = { "associations":{ "books":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", + "implementation": "foreignkey", "target": "post_book", "targetKey": "author_ids", "sourceKey": "book_ids", @@ -701,8 +737,8 @@ module.exports.author_ddm_array_fk ={ "associations":{ "books":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", + "implementation": "foreignkey", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", @@ -728,8 +764,8 @@ module.exports.author_sql_adapter_array_fk ={ "associations":{ "books":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", + "implementation": "foreignkey", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", @@ -757,8 +793,8 @@ module.exports.author_zendro_adapter_array_fk ={ "associations":{ "books":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", + "implementation": "foreignkey", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/unit_test_misc/data_models_cassandra.js b/test/unit_test_misc/data_models_cassandra.js index c87095cd..134069ba 100644 --- a/test/unit_test_misc/data_models_cassandra.js +++ b/test/unit_test_misc/data_models_cassandra.js @@ -15,13 +15,13 @@ module.exports.city = { }, "associations": { "rivers": { - "type": "to_many", + "type": "many_to_many", + "implementation": "foreignkey", "target": "river", "targetStorageType": "sql", "sourceKey": "river_ids", "targetKey": "city_ids", "keyIn": "city", - "reverseAssociationType": "to_many" } }, "internalId": "city_id" @@ -40,14 +40,16 @@ module.exports.incident = { "associations": { "instants": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Instant", "targetKey": "incident_assoc_id", "keyIn" : "Instant", "targetStorageType": "cassandra" }, "town": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "capital", "targetKey": "capital_id", "keyIn" : "Incident", @@ -73,7 +75,8 @@ module.exports.dist_incident = { "associations": { "dist_instants": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Dist_instant", "targetKey": "incident_assoc_id", "keyIn" : "Dist_instant", @@ -99,7 +102,8 @@ module.exports.dist_instant_instance1 = { "associations": { "dist_instants": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Dist_instant", "targetKey": "incident_assoc_id", "keyIn": "Dist_instant", diff --git a/test/unit_test_misc/data_models_distributed.js b/test/unit_test_misc/data_models_distributed.js index f45fad90..8f036f7b 100644 --- a/test/unit_test_misc/data_models_distributed.js +++ b/test/unit_test_misc/data_models_distributed.js @@ -12,7 +12,8 @@ module.exports.book = { "associations":{ "Authors" : { - "type" : "to_many", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Person", "targetKey" : "personId", "sourceKey" : "bookId", @@ -22,7 +23,8 @@ module.exports.book = { "sublabel" : "email" }, "publisher" : { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "publi_sher", "targetKey" : "publisher_id", "keyIn" : "Book", @@ -46,7 +48,8 @@ module.exports.book_ddm = "associations":{ "Authors" : { - "type" : "to_many", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Person", "targetKey" : "personId", "sourceKey" : "bookId", @@ -56,7 +59,8 @@ module.exports.book_ddm = "sublabel" : "email" }, "publisher" : { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "publi_sher", "targetKey" : "publisher_id", "keyIn" : "Book", @@ -80,7 +84,8 @@ module.exports.person_ddm = { "associations" : { "works" : { - "type": "to_many", + "type": "many_to_many", + "implementation": "sql_cross_table", "target": "Book", "targetKey": "bookId", "sourceKey": "personId", @@ -89,7 +94,8 @@ module.exports.person_ddm = { }, "company":{ - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "publi_sher", "targetKey": "companyId", "keyIn": "Person", @@ -97,7 +103,8 @@ module.exports.person_ddm = { }, "dogs" :{ - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Dog", "targetKey": "personId", "keyIn": "Dog", @@ -105,7 +112,8 @@ module.exports.person_ddm = { }, "parrot" :{ - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Parrot", "targetKey": "personId", "keyIn": "Parrot", @@ -128,7 +136,8 @@ module.exports.dog_ddm = { "associations" : { "owner" : { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "Person", "targetKey" : "personId", "keyIn" : "Dog", @@ -153,7 +162,8 @@ module.exports.dog_ddm = { }, "associations": { "works": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Book", "targetKey": "internalPersonId", "keyIn": "Book", @@ -199,7 +209,8 @@ module.exports.dog_ddm = { }, "associations": { "author": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Person", "targetKey": "internalPersonId", "keyIn": "Book", @@ -221,7 +232,8 @@ module.exports.dog_ddm_integration_test = { }, "associations": { "person": { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "person", "targetKey" : "person_id", "keyIn": "dog", @@ -246,7 +258,8 @@ module.exports.dog_zendro_adapter_integration_test = }, "associations": { "person": { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "person", "targetKey" : "person_id", "keyIn": "dog", diff --git a/test/unit_test_misc/data_models_extendedId.js b/test/unit_test_misc/data_models_extendedId.js index f797a201..eb1f6c48 100644 --- a/test/unit_test_misc/data_models_extendedId.js +++ b/test/unit_test_misc/data_models_extendedId.js @@ -12,7 +12,8 @@ module.exports.book_adapter = { }, "associations": { "author": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Person", "targetKey": "internalPersonId", "keyIn": "Book", @@ -38,7 +39,8 @@ module.exports.book_ddm = { }, "associations": { "author": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Person", "targetKey": "internalPersonId", "keyIn": "Book", @@ -64,7 +66,8 @@ module.exports.person_adapter = { }, "associations": { "works": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Book", "targetKey": "internalPersonId", "keyIn": "Book", @@ -91,7 +94,8 @@ module.exports.person_ddm = { }, "associations": { "works": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Book", "targetKey": "internalPersonId", "keyIn": "Book", diff --git a/test/unit_test_misc/data_models_generic.js b/test/unit_test_misc/data_models_generic.js index a89f0cbe..b120fda8 100644 --- a/test/unit_test_misc/data_models_generic.js +++ b/test/unit_test_misc/data_models_generic.js @@ -22,7 +22,8 @@ module.exports.personSql_toMany_dogGeneric = { }, "associations":{ "dogs":{ - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", "keyIn": "Dog", @@ -42,7 +43,8 @@ module.exports.dogGeneric_toOne_personSql = { }, "associations" : { "owner" : { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "Person", "targetKey" : "personId", "keyIn": "Dog", @@ -66,7 +68,8 @@ module.exports.personSql_toOne_hometownGeneric = { }, "associations":{ "unique_homeTown":{ - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "Hometown", "targetKey" : "hometownId", "keyIn": "Person", @@ -88,7 +91,8 @@ module.exports.hometownGeneric_toMany_personSql = { }, "associations" : { "people" : { - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", "target" : "Person", "targetKey" : "hometownId", "keyIn": "Person", @@ -111,7 +115,8 @@ module.exports.dogGeneric_genericToOne_person = { }, "associations" : { "owner" : { - "type" : "generic_to_one", + "type" : "many_to_one", + "implementation": "generic", "target" : "Person" } } @@ -130,7 +135,8 @@ module.exports.personSql_genericToMany_dog = { }, "associations":{ "dogs": { - "type": "generic_to_many", + "type": "one_to_many", + "implementation": "generic", "target": "Dog" } }, @@ -149,7 +155,8 @@ module.exports.dogDdm_genericToOne_person = { }, "associations" : { "owner" : { - "type" : "generic_to_one", + "type" : "many_to_one", + "implementation": "generic", "target" : "Person" } } @@ -169,7 +176,8 @@ module.exports.personDdm_genericToMany_dog = { }, "associations":{ "dogs": { - "type": "generic_to_many", + "type": "one_to_many", + "implementation": "generic", "target": "Dog" } }, diff --git a/test/unit_test_misc/data_models_generic_webservice.js b/test/unit_test_misc/data_models_generic_webservice.js index fc1aa541..63f861e4 100644 --- a/test/unit_test_misc/data_models_generic_webservice.js +++ b/test/unit_test_misc/data_models_generic_webservice.js @@ -10,7 +10,8 @@ module.exports.book = }, "associations": { "publisher" : { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "publi_sher", "targetKey": "publisher_id", "keyIn": "book", @@ -18,7 +19,8 @@ module.exports.book = }, "authors": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Person", "targetKey": "person_id", "sourceKey": "book_id", @@ -40,7 +42,8 @@ module.exports.person = "associations" : { "works" : { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "book", "targetKey": "book_id", "sourceKey": "person_id", @@ -48,7 +51,8 @@ module.exports.person = }, "company":{ - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "publi_sher", "targetKey": "companyId", "keyIn": "Person", @@ -69,7 +73,8 @@ module.exports.publisher = "associations": { "publications" : { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "book", "targetKey": "publisher_id", "keyIn": "book", @@ -77,7 +82,8 @@ module.exports.publisher = }, "director":{ - "type":"to_one", + "type":"many_to_one", + "implementation": "foreignkey", "target": "Person", "targetKey": "companyId", "keyIn": "Person", diff --git a/test/unit_test_misc/data_models_mongodb.js b/test/unit_test_misc/data_models_mongodb.js index b92c2fc1..caae1074 100644 --- a/test/unit_test_misc/data_models_mongodb.js +++ b/test/unit_test_misc/data_models_mongodb.js @@ -15,7 +15,8 @@ module.exports.animal = { }, associations: { farm: { - type: "to_one", + type: "many_to_one", + implementation: "foreignkey", target: "farm", targetKey: "farm_id", keyIn: "animal", @@ -23,8 +24,8 @@ module.exports.animal = { label: "farm_name", }, food: { - type: "to_many", - reverseAssociationType: "to_many", + type: "many_to_many", + implementation: "foreignkey", target: "food", targetKey: "animal_ids", sourceKey: "food_ids", @@ -58,7 +59,8 @@ module.exports.dist_animal_instance1 = { associations: { dist_farm: { - type: "to_one", + type: "many_to_one", + implementation: "foreignkey", target: "dist_farm", targetKey: "farm_id", keyIn: "dist_animal", diff --git a/test/unit_test_misc/data_models_refactoring.js b/test/unit_test_misc/data_models_refactoring.js index 6220e3de..9b9500f2 100644 --- a/test/unit_test_misc/data_models_refactoring.js +++ b/test/unit_test_misc/data_models_refactoring.js @@ -12,7 +12,8 @@ module.exports.accession = { "associations": { "individuals": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Individual", "targetKey": "accessionId", "keyIn" : "Individual", @@ -21,7 +22,8 @@ module.exports.accession = { }, "location": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Location", "targetKey": "locationId", "keyIn" : "Accession", @@ -31,7 +33,8 @@ module.exports.accession = { }, "measurements": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Measurement", "targetKey": "accessionId", "keyIn" : "Measurement", @@ -59,7 +62,8 @@ module.exports.accession_ddm = { "associations": { "individuals": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Individual", "targetKey": "accessionId", "keyIn" : "Individual", @@ -68,7 +72,8 @@ module.exports.accession_ddm = { }, "location": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Location", "targetKey": "locationId", "keyIn" : "Accession", @@ -78,7 +83,8 @@ module.exports.accession_ddm = { }, "measurements": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Measurement", "targetKey": "accessionId", "keyIn" : "Measurement", @@ -107,7 +113,8 @@ module.exports.accession_sql_adapter = { "associations": { "individuals": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Individual", "targetKey": "accessionId", "keyIn" : "Individual", @@ -116,7 +123,8 @@ module.exports.accession_sql_adapter = { }, "location": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Location", "targetKey": "locationId", "keyIn" : "Accession", @@ -126,7 +134,8 @@ module.exports.accession_sql_adapter = { }, "measurements": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Measurement", "targetKey": "accession_id", "keyIn" : "Measurement", @@ -155,7 +164,8 @@ module.exports.accession_zendro_adapter = { "associations": { "individuals": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Individual", "targetKey": "accessionId", "keyIn" : "Individual", @@ -165,7 +175,8 @@ module.exports.accession_zendro_adapter = { "location": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Location", "targetKey": "locationId", "keyIn" : "Accession", @@ -175,7 +186,8 @@ module.exports.accession_zendro_adapter = { }, "measurements": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Measurement", "targetKey": "accession_id", "keyIn" : "Measurement", diff --git a/test/unit_test_misc/data_models_zendro.js b/test/unit_test_misc/data_models_zendro.js index 67acd1b4..01a0f8db 100644 --- a/test/unit_test_misc/data_models_zendro.js +++ b/test/unit_test_misc/data_models_zendro.js @@ -10,7 +10,8 @@ module.exports.book = { "associations":{ "Authors" : { - "type" : "to_many", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Person", "targetKey" : "personId", "sourceKey" : "bookId", @@ -20,7 +21,8 @@ module.exports.book = { "sublabel" : "email" }, "publisher" : { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "publi_sher", "targetKey" : "publisher_id", "keyIn" : "Book", @@ -42,7 +44,8 @@ module.exports.person = { }, "associations":{ "works":{ - "type" : "to_many", + "type" : "many_to_many", + "implementation": "sql_cross_table", "target" : "Book", "targetKey" : "bookId", "sourceKey" : "personId", @@ -52,7 +55,8 @@ module.exports.person = { }, "company":{ - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "publi_sher", "targetKey": "companyId", "keyIn": "Person", @@ -74,7 +78,8 @@ module.exports.dog_one_assoc = { "associations" : { "owner" : { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "Person", "targetKey" : "personId", "keyIn" : "Dog", @@ -82,7 +87,8 @@ module.exports.dog_one_assoc = { }, "veterinarian" : { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", "target" : "Person", "targetKey" : "veterinarianId", "keyIn" : "Dog", @@ -104,7 +110,8 @@ module.exports.person_one_assoc = { "associations" : { "unique_pet" :{ - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Dog", "targetKey": "personId", "keyIn": "Dog", @@ -112,7 +119,8 @@ module.exports.person_one_assoc = { }, "patients" : { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Dog", "targetKey": "veterinarianId", "keyIn": "Dog", diff --git a/test/unit_test_misc/test-describe/distributed-models.js b/test/unit_test_misc/test-describe/distributed-models.js index 2670362c..a0fce6cb 100644 --- a/test/unit_test_misc/test-describe/distributed-models.js +++ b/test/unit_test_misc/test-describe/distributed-models.js @@ -328,7 +328,8 @@ const definition = { }, associations: { works: { - type: 'to_many', + type: 'many_to_many', + implementation: 'sql_cross_table', target: 'Book', targetKey: 'bookId', sourceKey: 'personId', @@ -336,21 +337,24 @@ const definition = { targetStorageType: 'sql' }, company: { - type: 'to_one', + type: 'many_to_one', + implementation: 'foreignkey', target: 'publi_sher', targetKey: 'companyId', keyIn: 'Person', targetStorageType: 'zendro-server' }, dogs: { - type: 'to_many', + type: 'one_to_many', + implementation: 'foreignkey', target: 'Dog', targetKey: 'personId', keyIn: 'Dog', targetStorageType: 'sql' }, parrot: { - type: 'to_one', + type: 'many_to_one', + implementation: 'foreignkey', target: 'Parrot', targetKey: 'personId', keyIn: 'Parrot', @@ -378,7 +382,8 @@ const definition = { }, associations: { owner: { - type: 'to_one', + type: 'many_to_one', + implementation: 'foreignkey', target: 'Person', targetKey: 'personId', keyIn: 'Dog', diff --git a/test/unit_test_misc/test-describe/zendro-servers.js b/test/unit_test_misc/test-describe/zendro-servers.js index 5760cece..42b3e4c1 100644 --- a/test/unit_test_misc/test-describe/zendro-servers.js +++ b/test/unit_test_misc/test-describe/zendro-servers.js @@ -259,7 +259,8 @@ const definition = { }, associations: { works: { - type: 'to_many', + type: 'many_to_many', + implementation: 'sql_cross_table', target: 'Book', targetKey: 'bookId', sourceKey: 'personId', @@ -268,7 +269,8 @@ const definition = { label: 'title' }, company: { - type: 'to_one', + type: 'many_to_one', + implementation: 'foreignkey', target: 'publi_sher', targetKey: 'companyId', keyIn: 'Person', From 992c7515dbfd5cb6500c5b59dc12058b2fcdf25b Mon Sep 17 00:00:00 2001 From: coeit Date: Tue, 8 Jun 2021 18:41:30 +0200 Subject: [PATCH 03/18] refactor: new association types for integration test models --- .../accession.json | 12 ++++--- .../amino_acid_sequence.json | 19 +++++----- .../animal.json | 20 ++++++----- .../arr.json | 4 +-- .../author.json | 14 ++++---- .../book.json | 14 ++++---- .../capital.json | 22 ++++++------ .../cassandra-city.json | 12 +++---- .../cassandra-incident.json | 12 ++++--- .../cassandra-instant.json | 7 ++-- .../country.json | 24 +++++++------ .../country_to_river.json | 10 +++--- .../dist_animal.json | 9 ++--- .../dist_animal_instance1.json | 3 +- .../dist_farm.json | 5 +-- .../dist_farm_instance1.json | 3 +- .../dist_incident.json | 9 ++--- .../dist_incident_instance1.json | 3 +- .../dist_instant.json | 9 ++--- .../dist_instant_instance1.json | 3 +- .../dist_reader.json | 4 +-- .../dog.json | 15 ++++---- .../dog_instance1_adapter.json | 15 ++++---- .../dog_instance2_adapter.json | 15 ++++---- .../experiment.json | 4 +-- .../farm.json | 3 +- .../food.json | 16 ++++----- .../individual.json | 17 ++++----- .../location.json | 9 ++--- .../measurement.json | 7 ++-- .../parrot.json | 17 ++++----- .../parrot_instance1_adapter.json | 17 ++++----- .../parrot_instance2_adapter.json | 17 ++++----- .../person.json | 26 +++++++------- .../person_instance1_adapter.json | 26 +++++++------- .../person_instance2_adapter.json | 26 +++++++------- .../river.json | 21 +++++------ .../sq_author.json | 14 ++++---- .../sq_book.json | 14 ++++---- .../tracker.json | 17 ++++----- .../transcript_count.json | 36 ++++++++++--------- .../accession.json | 11 +++--- .../author.json | 9 +++-- .../book.json | 9 +++-- .../dist_presto_doctor.json | 4 +-- .../dist_trino_doctor.json | 4 +-- .../dog.json | 17 ++++----- .../dog_instance1_adapter.json | 17 ++++----- .../dog_instance2_adapter.json | 17 ++++----- .../location.json | 6 ++-- .../measurement.json | 7 ++-- .../parrot.json | 17 ++++----- .../parrot_instance1_adapter.json | 17 ++++----- .../parrot_instance2_adapter.json | 17 ++++----- .../person.json | 25 ++++++------- .../person_instance1_adapter.json | 25 ++++++------- .../person_instance2_adapter.json | 25 ++++++------- .../sq_author_adapter.json | 9 +++-- .../sq_author_ddm.json | 9 +++-- .../sq_author_zendro_adapter.json | 9 +++-- .../sq_book_adapter.json | 9 +++-- .../sq_book_ddm.json | 9 +++-- .../sq_book_zendro_adapter.json | 9 +++-- 63 files changed, 437 insertions(+), 394 deletions(-) diff --git a/test/integration_test_misc/integration_test_models_instance1/accession.json b/test/integration_test_misc/integration_test_models_instance1/accession.json index 6751f6d3..5b20b6ff 100644 --- a/test/integration_test_misc/integration_test_models_instance1/accession.json +++ b/test/integration_test_misc/integration_test_models_instance1/accession.json @@ -12,24 +12,26 @@ "associations": { "location": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Location", "targetKey": "locationId", - "keyIn" : "Accession", + "keyIn": "Accession", "targetStorageType": "sql", "label": "country", "sublabel": "state" }, "measurements": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Measurement", "targetKey": "accessionId", - "keyIn" : "Measurement", + "keyIn": "Measurement", "targetStorageType": "sql", "label": "name" } }, - "internalId" : "accession_id" + "internalId": "accession_id" } diff --git a/test/integration_test_misc/integration_test_models_instance1/amino_acid_sequence.json b/test/integration_test_misc/integration_test_models_instance1/amino_acid_sequence.json index 11b2492e..5f175338 100644 --- a/test/integration_test_misc/integration_test_models_instance1/amino_acid_sequence.json +++ b/test/integration_test_misc/integration_test_models_instance1/amino_acid_sequence.json @@ -1,17 +1,18 @@ { - "model" : "aminoacidsequence", - "storageType" : "generic", - "attributes" : { - "accession" : "String", - "sequence" : "String" + "model": "aminoacidsequence", + "storageType": "generic", + "attributes": { + "accession": "String", + "sequence": "String" }, "associations": { "transcript_counts": { - "type" : "to_many", - "target" : "transcript_count", - "targetKey" : "aminoacidsequence_id", + "type": "one_to_many", + "implementation": "foreignkey", + "target": "transcript_count", + "targetKey": "aminoacidsequence_id", "keyIn": "transcript_count", - "targetStorageType" : "sql" + "targetStorageType": "sql" } } } diff --git a/test/integration_test_misc/integration_test_models_instance1/animal.json b/test/integration_test_misc/integration_test_models_instance1/animal.json index c9e5c473..57ec0db1 100644 --- a/test/integration_test_misc/integration_test_models_instance1/animal.json +++ b/test/integration_test_misc/integration_test_models_instance1/animal.json @@ -15,28 +15,30 @@ }, "associations": { "farm": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "farm", "targetKey": "farm_id", "keyIn": "animal", "targetStorageType": "mongodb", "label": "farm_name" }, - "food":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "food": { + "type": "many_to_many", + "implementation": "foreignkey", "target": "food", "targetKey": "animal_ids", "sourceKey": "food_ids", "keyIn": "animal", "targetStorageType": "mongodb" }, - "unique_tracker":{ - "type" : "to_one", - "target" : "tracker", - "targetKey" : "animal_id", + "unique_tracker": { + "type": "one_to_one", + "implementation": "foreignkey", + "target": "tracker", + "targetKey": "animal_id", "keyIn": "tracker", - "targetStorageType" : "mongodb" + "targetStorageType": "mongodb" } }, "internalId": "animal_id", diff --git a/test/integration_test_misc/integration_test_models_instance1/arr.json b/test/integration_test_misc/integration_test_models_instance1/arr.json index 89ddaeb0..7e961c5b 100644 --- a/test/integration_test_misc/integration_test_models_instance1/arr.json +++ b/test/integration_test_misc/integration_test_models_instance1/arr.json @@ -1,7 +1,7 @@ { "model": "Arr", "storageType": "sql", - "attributes" : { + "attributes": { "arrId": "String", "country": "String", "singleTime": "Time", @@ -14,7 +14,7 @@ "arrDateTime": "[DateTime]" }, - "internalId" : "arrId" + "internalId": "arrId" } \ No newline at end of file diff --git a/test/integration_test_misc/integration_test_models_instance1/author.json b/test/integration_test_misc/integration_test_models_instance1/author.json index 4b68be20..18454f87 100644 --- a/test/integration_test_misc/integration_test_models_instance1/author.json +++ b/test/integration_test_misc/integration_test_models_instance1/author.json @@ -1,8 +1,8 @@ { - "model" : "author", - "storageType" : "sql", + "model": "author", + "storageType": "sql", "database": "default-sql", - "attributes" : { + "attributes": { "id": "String", "name": "String", "lastname": "String", @@ -10,10 +10,10 @@ "book_ids": "[String]" }, - "associations":{ - "books":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "associations": { + "books": { + "type": "many_to_many", + "implementation": "foreignkey", "target": "book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance1/book.json b/test/integration_test_misc/integration_test_models_instance1/book.json index 7179b633..89054737 100644 --- a/test/integration_test_misc/integration_test_models_instance1/book.json +++ b/test/integration_test_misc/integration_test_models_instance1/book.json @@ -1,8 +1,8 @@ { - "model" : "book", - "storageType" : "sql", + "model": "book", + "storageType": "sql", "database": "default-sql", - "attributes" : { + "attributes": { "id": "String", "title": "String", "genre": "String", @@ -10,10 +10,10 @@ "author_ids": "[String]" }, - "associations":{ - "authors":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "associations": { + "authors": { + "type": "many_to_many", + "implementation": "foreignkey", "target": "author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/integration_test_misc/integration_test_models_instance1/capital.json b/test/integration_test_misc/integration_test_models_instance1/capital.json index b696a9aa..420c399e 100644 --- a/test/integration_test_misc/integration_test_models_instance1/capital.json +++ b/test/integration_test_misc/integration_test_models_instance1/capital.json @@ -1,21 +1,23 @@ { - "model" : "capital", - "storageType" : "SQL", - "attributes" : { - "name" : "String", + "model": "capital", + "storageType": "SQL", + "attributes": { + "name": "String", "country_id": "String", - "capital_id" : "String" + "capital_id": "String" }, "associations": { "unique_country": { - "type" : "to_one", - "target" : "country", - "targetKey" : "country_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "country", + "targetKey": "country_id", "keyIn": "capital", - "targetStorageType" : "sql" + "targetStorageType": "sql" }, "incidents": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Incident", "targetKey": "capital_id", "keyIn": "Incident", diff --git a/test/integration_test_misc/integration_test_models_instance1/cassandra-city.json b/test/integration_test_misc/integration_test_models_instance1/cassandra-city.json index 09ed7f42..1092124b 100644 --- a/test/integration_test_misc/integration_test_models_instance1/cassandra-city.json +++ b/test/integration_test_misc/integration_test_models_instance1/cassandra-city.json @@ -1,7 +1,7 @@ { - "model" : "city", - "storageType" : "cassandra", - "attributes" : { + "model": "city", + "storageType": "cassandra", + "attributes": { "city_id": "String", "name": "String", @@ -15,13 +15,13 @@ }, "associations": { "rivers": { - "type": "to_many", + "type": "many_to_many", + "implementation": "foreignkey", "target": "river", "targetStorageType": "sql", "sourceKey": "river_ids", "targetKey": "city_ids", - "keyIn": "city", - "reverseAssociationType":"to_many" + "keyIn": "city" } }, "internalId": "city_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/cassandra-incident.json b/test/integration_test_misc/integration_test_models_instance1/cassandra-incident.json index d4ac9df2..e3d66a1d 100644 --- a/test/integration_test_misc/integration_test_models_instance1/cassandra-incident.json +++ b/test/integration_test_misc/integration_test_models_instance1/cassandra-incident.json @@ -11,21 +11,23 @@ "associations": { "instants": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Instant", "targetKey": "incident_assoc_id", - "keyIn" : "Instant", + "keyIn": "Instant", "targetStorageType": "cassandra" }, "town": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "capital", "targetKey": "capital_id", - "keyIn" : "Incident", + "keyIn": "Incident", "targetStorageType": "sql" } }, - "internalId" : "incident_id" + "internalId": "incident_id" } diff --git a/test/integration_test_misc/integration_test_models_instance1/cassandra-instant.json b/test/integration_test_misc/integration_test_models_instance1/cassandra-instant.json index 2a6b01df..e1784740 100644 --- a/test/integration_test_misc/integration_test_models_instance1/cassandra-instant.json +++ b/test/integration_test_misc/integration_test_models_instance1/cassandra-instant.json @@ -14,14 +14,15 @@ "associations": { "incident": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Incident", "targetKey": "incident_assoc_id", - "keyIn" : "Instant", + "keyIn": "Instant", "targetStorageType": "cassandra" } }, - "internalId" : "instant_id" + "internalId": "instant_id" } diff --git a/test/integration_test_misc/integration_test_models_instance1/country.json b/test/integration_test_misc/integration_test_models_instance1/country.json index 15106627..798db811 100644 --- a/test/integration_test_misc/integration_test_models_instance1/country.json +++ b/test/integration_test_misc/integration_test_models_instance1/country.json @@ -1,25 +1,27 @@ { - "model" : "country", - "storageType" : "SQL", - "attributes" : { - "name" : "String", - "country_id" : "String" + "model": "country", + "storageType": "SQL", + "attributes": { + "name": "String", + "country_id": "String" }, "associations": { "unique_capital": { - "type" : "to_one", - "target" : "capital", - "targetKey" : "country_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "capital", + "targetKey": "country_id", "keyIn": "capital", - "targetStorageType" : "sql" + "targetStorageType": "sql" }, "rivers": { - "type" : "to_many_through_sql_cross_table", + "type": "many_to_many", + "implementation": "sql_cross_table", "target": "river", "sourceKey": "country_id", "targetKey": "river_id", "keysIn": "country_to_river", - "targetStorageType" : "sql" + "targetStorageType": "sql" } }, "internalId": "country_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/country_to_river.json b/test/integration_test_misc/integration_test_models_instance1/country_to_river.json index c40a3214..688ef690 100644 --- a/test/integration_test_misc/integration_test_models_instance1/country_to_river.json +++ b/test/integration_test_misc/integration_test_models_instance1/country_to_river.json @@ -1,8 +1,8 @@ { - "model" : "country_to_river", - "storageType" : "SQL", - "attributes" : { - "country_id" : "String", - "river_id" : "String" + "model": "country_to_river", + "storageType": "SQL", + "attributes": { + "country_id": "String", + "river_id": "String" } } diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_animal.json b/test/integration_test_misc/integration_test_models_instance1/dist_animal.json index bcecb3a3..449488f9 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_animal.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_animal.json @@ -1,6 +1,6 @@ { "model": "dist_animal", - "storageType" : "distributed-data-model", + "storageType": "distributed-data-model", "registry": ["dist_animal_instance1"], "attributes": { "animal_id": "String", @@ -16,13 +16,14 @@ "associations": { "dist_farm": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "dist_farm", "targetKey": "farm_id", - "keyIn" : "dist_animal", + "keyIn": "dist_animal", "targetStorageType": "distributed-data-model" } }, - "internalId" : "animal_id" + "internalId": "animal_id" } \ No newline at end of file diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_animal_instance1.json b/test/integration_test_misc/integration_test_models_instance1/dist_animal_instance1.json index b5eac6a5..3d47488a 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_animal_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_animal_instance1.json @@ -18,7 +18,8 @@ "associations": { "dist_farm": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "dist_farm", "targetKey": "farm_id", "keyIn": "dist_animal", diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_farm.json b/test/integration_test_misc/integration_test_models_instance1/dist_farm.json index 4f4f692d..980e4c0d 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_farm.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_farm.json @@ -1,6 +1,6 @@ { "model": "dist_farm", - "storageType" : "distributed-data-model", + "storageType": "distributed-data-model", "registry": ["dist_farm_instance1"], "attributes": { "farm_id": "String", @@ -9,7 +9,8 @@ }, "associations": { "dist_animals": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "dist_animal", "targetKey": "farm_id", "keyIn": "dist_animal", diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_farm_instance1.json b/test/integration_test_misc/integration_test_models_instance1/dist_farm_instance1.json index 8df5fa83..6579befc 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_farm_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_farm_instance1.json @@ -10,7 +10,8 @@ }, "associations": { "dist_animals": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "dist_animal", "targetKey": "farm_id", "keyIn": "dist_animal", diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_incident.json b/test/integration_test_misc/integration_test_models_instance1/dist_incident.json index 6fbc44c1..a7f23958 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_incident.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_incident.json @@ -1,6 +1,6 @@ { "model": "Dist_incident", - "storageType" : "distributed-data-model", + "storageType": "distributed-data-model", "registry": ["dist_incident_instance1"], "cassandraRestrictions": true, "attributes": { @@ -12,14 +12,15 @@ "associations": { "dist_instants": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Dist_instant", "targetKey": "incident_assoc_id", - "keyIn" : "Dist_instant", + "keyIn": "Dist_instant", "targetStorageType": "distributed-data-model" } }, - "internalId" : "incident_id" + "internalId": "incident_id" } diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_incident_instance1.json b/test/integration_test_misc/integration_test_models_instance1/dist_incident_instance1.json index 47672fa6..f7cb81bc 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_incident_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_incident_instance1.json @@ -12,7 +12,8 @@ "associations": { "dist_instants": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Dist_instant", "targetKey": "incident_assoc_id", "keyIn": "Dist_instant", diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_instant.json b/test/integration_test_misc/integration_test_models_instance1/dist_instant.json index 356ec0cd..58361e35 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_instant.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_instant.json @@ -1,6 +1,6 @@ { "model": "Dist_instant", - "storageType" : "distributed-data-model", + "storageType": "distributed-data-model", "registry": ["dist_instant_instance1"], "cassandraRestrictions": true, "attributes": { @@ -16,14 +16,15 @@ "associations": { "dist_incident": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Dist_incident", "targetKey": "incident_assoc_id", - "keyIn" : "Dist_instant", + "keyIn": "Dist_instant", "targetStorageType": "distributed-data-model" } }, - "internalId" : "instant_id" + "internalId": "instant_id" } diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_instant_instance1.json b/test/integration_test_misc/integration_test_models_instance1/dist_instant_instance1.json index fcc97e99..09f4b366 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_instant_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_instant_instance1.json @@ -16,7 +16,8 @@ "associations": { "dist_incident": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Dist_incident", "targetKey": "incident_assoc_id", "keyIn": "Dist_instant", diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_reader.json b/test/integration_test_misc/integration_test_models_instance1/dist_reader.json index fae822b8..951a4d0f 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_reader.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_reader.json @@ -1,6 +1,6 @@ { "model": "dist_reader", - "storageType" : "distributed-data-model", + "storageType": "distributed-data-model", "registry": ["dist_reader_instance1"], "attributes": { "reader_id": "String", @@ -11,5 +11,5 @@ "history": "[String]" }, - "internalId" : "reader_id" + "internalId": "reader_id" } \ No newline at end of file diff --git a/test/integration_test_misc/integration_test_models_instance1/dog.json b/test/integration_test_misc/integration_test_models_instance1/dog.json index a0327b87..f8a6aadc 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dog.json +++ b/test/integration_test_misc/integration_test_models_instance1/dog.json @@ -1,19 +1,20 @@ { - "model" : "dog", - "storageType" : "distributed-data-model", + "model": "dog", + "storageType": "distributed-data-model", "registry": ["dog_instance1", "dog_instance2"], - "attributes" : { + "attributes": { "name": "String", "dog_id": "String", "person_id": "String" }, "associations": { "person": { - "type" : "to_one", - "target" : "person", - "targetKey" : "person_id", + "type": "many_to_one", + "implementation": "foreignkey", + "target": "person", + "targetKey": "person_id", "keyIn": "dog", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "dog_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/dog_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance1/dog_instance1_adapter.json index 93f07f8b..da2baaf8 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dog_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/dog_instance1_adapter.json @@ -1,20 +1,21 @@ { - "model" : "dog", - "storageType" : "sql-adapter", + "model": "dog", + "storageType": "sql-adapter", "adapterName": "dog_instance1", "regex": "instance1", - "attributes" : { + "attributes": { "name": "String", "dog_id": "String", "person_id": "String" }, "associations": { "person": { - "type" : "to_one", - "target" : "person", - "targetKey" : "person_id", + "type": "many_to_one", + "implementation": "foreignkey", + "target": "person", + "targetKey": "person_id", "keyIn": "dog", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "dog_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/dog_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance1/dog_instance2_adapter.json index b660282a..c47bb80f 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dog_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/dog_instance2_adapter.json @@ -1,21 +1,22 @@ { - "model" : "dog", - "storageType" : "ddm-adapter", + "model": "dog", + "storageType": "ddm-adapter", "adapterName": "dog_instance2", "regex": "instance2", "url": "http://server2:3030/graphql", - "attributes" : { + "attributes": { "name": "String", "dog_id": "String", "person_id": "String" }, "associations": { "person": { - "type" : "to_one", - "target" : "person", - "targetKey" : "person_id", + "type": "many_to_one", + "implementation": "foreignkey", + "target": "person", + "targetKey": "person_id", "keyIn": "dog", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "dog_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/experiment.json b/test/integration_test_misc/integration_test_models_instance1/experiment.json index edbebebc..29030aca 100644 --- a/test/integration_test_misc/integration_test_models_instance1/experiment.json +++ b/test/integration_test_misc/integration_test_models_instance1/experiment.json @@ -1,7 +1,7 @@ { - "model" : "SequencingExperiment", + "model": "SequencingExperiment", "storageType": "sql", - "attributes":{ + "attributes": { "name": "String", "start_date": "Date", "end_date": "Date", diff --git a/test/integration_test_misc/integration_test_models_instance1/farm.json b/test/integration_test_misc/integration_test_models_instance1/farm.json index 29478a0e..7b75047c 100644 --- a/test/integration_test_misc/integration_test_models_instance1/farm.json +++ b/test/integration_test_misc/integration_test_models_instance1/farm.json @@ -8,7 +8,8 @@ }, "associations": { "animals": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "animal", "targetKey": "farm_id", "keyIn": "animal", diff --git a/test/integration_test_misc/integration_test_models_instance1/food.json b/test/integration_test_misc/integration_test_models_instance1/food.json index 272c86ab..e7bd9c07 100644 --- a/test/integration_test_misc/integration_test_models_instance1/food.json +++ b/test/integration_test_misc/integration_test_models_instance1/food.json @@ -1,16 +1,16 @@ { - "model" : "food", - "storageType" : "mongodb", - "attributes" : { + "model": "food", + "storageType": "mongodb", + "attributes": { "food_id": "String", "food_name": "String", "animal_ids": "[String]" }, - "associations":{ - "animals":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "associations": { + "animals": { + "type": "many_to_many", + "implementation": "foreignkey", "target": "animal", "targetKey": "food_ids", "sourceKey": "animal_ids", @@ -20,7 +20,7 @@ }, "internalId": "food_id", - "id":{ + "id": { "name": "food_id", "type": "String" } diff --git a/test/integration_test_misc/integration_test_models_instance1/individual.json b/test/integration_test_misc/integration_test_models_instance1/individual.json index 29357ba9..885f95a8 100644 --- a/test/integration_test_misc/integration_test_models_instance1/individual.json +++ b/test/integration_test_misc/integration_test_models_instance1/individual.json @@ -1,16 +1,17 @@ { - "model" : "individual", - "storageType" : "SQL", - "attributes" : { - "name" : "String" + "model": "individual", + "storageType": "SQL", + "attributes": { + "name": "String" }, "associations": { "transcript_counts": { - "type" : "to_many", - "target" : "transcript_count", - "targetKey" : "individual_id", + "type": "one_to_many", + "implementation": "foreignkey", + "target": "transcript_count", + "targetKey": "individual_id", "keyIn": "transcript_count", - "targetStorageType" : "sql" + "targetStorageType": "sql" } } } diff --git a/test/integration_test_misc/integration_test_models_instance1/location.json b/test/integration_test_misc/integration_test_models_instance1/location.json index dcf853b0..ca14b7e5 100644 --- a/test/integration_test_misc/integration_test_models_instance1/location.json +++ b/test/integration_test_misc/integration_test_models_instance1/location.json @@ -1,7 +1,7 @@ { "model": "Location", "storageType": "sql", - "attributes" : { + "attributes": { "locationId": "String", "country": "String", "state": "String", @@ -9,10 +9,11 @@ "locality": "String" }, - "associations" :{ + "associations": { "accessions": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkey", "target": "Accession", "targetKey": "locationId", "keyIn": "Accession", @@ -21,6 +22,6 @@ } }, - "internalId" : "locationId" + "internalId": "locationId" } diff --git a/test/integration_test_misc/integration_test_models_instance1/measurement.json b/test/integration_test_misc/integration_test_models_instance1/measurement.json index 59155367..978e0968 100644 --- a/test/integration_test_misc/integration_test_models_instance1/measurement.json +++ b/test/integration_test_misc/integration_test_models_instance1/measurement.json @@ -11,14 +11,15 @@ "associations": { "accession": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Accession", "targetKey": "accessionId", - "keyIn" : "Measurement", + "keyIn": "Measurement", "targetStorageType": "sql", "label": "accession_id" } }, - "internalId" : "measurement_id" + "internalId": "measurement_id" } diff --git a/test/integration_test_misc/integration_test_models_instance1/parrot.json b/test/integration_test_misc/integration_test_models_instance1/parrot.json index f838bd00..e73d1d99 100644 --- a/test/integration_test_misc/integration_test_models_instance1/parrot.json +++ b/test/integration_test_misc/integration_test_models_instance1/parrot.json @@ -1,19 +1,20 @@ { - "model" : "parrot", - "storageType" : "distributed-data-model", + "model": "parrot", + "storageType": "distributed-data-model", "registry": ["parrot_instance1", "parrot_instance2"], - "attributes" : { - "name" : "String", + "attributes": { + "name": "String", "parrot_id": "String", "person_id": "String" }, "associations": { "unique_person": { - "type" : "to_one", - "target" : "person", - "targetKey" : "person_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "person", + "targetKey": "person_id", "keyIn": "parrot", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "parrot_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/parrot_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance1/parrot_instance1_adapter.json index 73d08101..83cc99d1 100644 --- a/test/integration_test_misc/integration_test_models_instance1/parrot_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/parrot_instance1_adapter.json @@ -1,20 +1,21 @@ { - "model" : "parrot", - "storageType" : "sql-adapter", + "model": "parrot", + "storageType": "sql-adapter", "adapterName": "parrot_instance1", "regex": "instance1", - "attributes" : { - "name" : "String", + "attributes": { + "name": "String", "parrot_id": "String", "person_id": "String" }, "associations": { "unique_person": { - "type" : "to_one", - "target" : "person", - "targetKey" : "person_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "person", + "targetKey": "person_id", "keyIn": "parrot", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "parrot_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/parrot_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance1/parrot_instance2_adapter.json index 39b66a88..29a9e0ab 100644 --- a/test/integration_test_misc/integration_test_models_instance1/parrot_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/parrot_instance2_adapter.json @@ -1,21 +1,22 @@ { - "model" : "parrot", - "storageType" : "ddm-adapter", + "model": "parrot", + "storageType": "ddm-adapter", "adapterName": "parrot_instance2", "regex": "instance2", "url": "http://server2:3030/graphql", - "attributes" : { - "name" : "String", + "attributes": { + "name": "String", "parrot_id": "String", "person_id": "String" }, "associations": { "unique_person": { - "type" : "to_one", - "target" : "person", - "targetKey" : "person_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "person", + "targetKey": "person_id", "keyIn": "parrot", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "parrot_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/person.json b/test/integration_test_misc/integration_test_models_instance1/person.json index adc5cbe5..5da3badd 100644 --- a/test/integration_test_misc/integration_test_models_instance1/person.json +++ b/test/integration_test_misc/integration_test_models_instance1/person.json @@ -1,25 +1,27 @@ { - "model" : "person", - "storageType" : "distributed-data-model", + "model": "person", + "storageType": "distributed-data-model", "registry": ["person_instance1", "person_instance2"], - "attributes" : { - "name" : "String", + "attributes": { + "name": "String", "person_id": "String" }, "associations": { "dogs": { - "type" : "to_many", - "target" : "dog", - "targetKey" : "person_id", + "type": "one_to_many", + "implementation": "foreignkey", + "target": "dog", + "targetKey": "person_id", "keyIn": "dog", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" }, "unique_parrot": { - "type" : "to_one", - "target" : "parrot", - "targetKey" : "person_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "parrot", + "targetKey": "person_id", "keyIn": "parrot", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "person_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/person_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance1/person_instance1_adapter.json index fb1557f6..dfed0f54 100644 --- a/test/integration_test_misc/integration_test_models_instance1/person_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/person_instance1_adapter.json @@ -1,26 +1,28 @@ { - "model" : "person", - "storageType" : "sql-adapter", + "model": "person", + "storageType": "sql-adapter", "adapterName": "person_instance1", "regex": "instance1", - "attributes" : { - "name" : "String", + "attributes": { + "name": "String", "person_id": "String" }, "associations": { "dogs": { - "type" : "to_many", - "target" : "dog", - "targetKey" : "person_id", + "type": "one_to_many", + "implementation": "foreignkey", + "target": "dog", + "targetKey": "person_id", "keyIn": "dog", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" }, "unique_parrot": { - "type" : "to_one", - "target" : "parrot", - "targetKey" : "person_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "parrot", + "targetKey": "person_id", "keyIn": "parrot", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "person_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/person_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance1/person_instance2_adapter.json index c709aa46..5a83cbe3 100644 --- a/test/integration_test_misc/integration_test_models_instance1/person_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/person_instance2_adapter.json @@ -1,27 +1,29 @@ { - "model" : "person", - "storageType" : "ddm-adapter", + "model": "person", + "storageType": "ddm-adapter", "adapterName": "person_instance2", "regex": "instance2", "url": "http://server2:3030/graphql", - "attributes" : { - "name" : "String", + "attributes": { + "name": "String", "person_id": "String" }, "associations": { "dogs": { - "type" : "to_many", - "target" : "dog", - "targetKey" : "person_id", + "type": "one_to_many", + "implementation": "foreignkey", + "target": "dog", + "targetKey": "person_id", "keyIn": "dog", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" }, "unique_parrot": { - "type" : "to_one", - "target" : "parrot", - "targetKey" : "person_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "parrot", + "targetKey": "person_id", "keyIn": "parrot", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "person_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/river.json b/test/integration_test_misc/integration_test_models_instance1/river.json index fa73e300..c6dd4aee 100644 --- a/test/integration_test_misc/integration_test_models_instance1/river.json +++ b/test/integration_test_misc/integration_test_models_instance1/river.json @@ -1,30 +1,31 @@ { - "model" : "river", - "storageType" : "SQL", - "attributes" : { - "name" : "String", - "length" : "Int", + "model": "river", + "storageType": "SQL", + "attributes": { + "name": "String", + "length": "Int", "river_id": "String", "city_ids": "[String]" }, "associations": { "countries": { - "type" : "to_many_through_sql_cross_table", + "type": "many_to_many", + "implementation": "sql_cross_table", "target": "country", "sourceKey": "river_id", "targetKey": "country_id", "keysIn": "country_to_river", - "targetStorageType" : "sql" + "targetStorageType": "sql" }, "cities": { - "type": "to_many", + "type": "many_to_many", + "implementation": "foreignkey", "target": "city", "targetStorageType": "cassandra", "sourceKey": "city_ids", "targetKey": "river_ids", - "keyIn": "river", - "reverseAssociationType":"to_many" + "keyIn": "river" } }, "internalId": "river_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/sq_author.json b/test/integration_test_misc/integration_test_models_instance1/sq_author.json index fddf4e69..528284b6 100644 --- a/test/integration_test_misc/integration_test_models_instance1/sq_author.json +++ b/test/integration_test_misc/integration_test_models_instance1/sq_author.json @@ -1,18 +1,18 @@ { - "model" : "sq_author", - "storageType" : "sql", + "model": "sq_author", + "storageType": "sql", "database": "default-sql", - "attributes" : { + "attributes": { "id": "String", "name": "String", "lastname": "String", "email": "String", "book_ids": "[ String ]" }, - "associations":{ - "books":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "associations": { + "books": { + "type": "many_to_many", + "implementation": "foreignkey", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance1/sq_book.json b/test/integration_test_misc/integration_test_models_instance1/sq_book.json index ff0e337f..a6159372 100644 --- a/test/integration_test_misc/integration_test_models_instance1/sq_book.json +++ b/test/integration_test_misc/integration_test_models_instance1/sq_book.json @@ -1,8 +1,8 @@ { - "model" : "sq_book", - "storageType" : "sql", + "model": "sq_book", + "storageType": "sql", "database": "default-sql", - "attributes" : { + "attributes": { "id": "String", "title": "String", "genre": "String", @@ -10,10 +10,10 @@ "author_ids": "[ String]" }, - "associations":{ - "authors":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "associations": { + "authors": { + "type": "many_to_many", + "implementation": "foreignkey", "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/integration_test_misc/integration_test_models_instance1/tracker.json b/test/integration_test_misc/integration_test_models_instance1/tracker.json index 26d158d6..c35a2b9d 100644 --- a/test/integration_test_misc/integration_test_models_instance1/tracker.json +++ b/test/integration_test_misc/integration_test_models_instance1/tracker.json @@ -1,18 +1,19 @@ { - "model" : "tracker", - "storageType" : "mongodb", - "attributes" : { + "model": "tracker", + "storageType": "mongodb", + "attributes": { "tracker_id": "String", - "animal_id" : "String", + "animal_id": "String", "location": "String" }, "associations": { "unique_animal": { - "type" : "to_one", - "target" : "animal", - "targetKey" : "animal_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "animal", + "targetKey": "animal_id", "keyIn": "tracker", - "targetStorageType" : "mongodb" + "targetStorageType": "mongodb" } }, "internalId": "tracker_id", diff --git a/test/integration_test_misc/integration_test_models_instance1/transcript_count.json b/test/integration_test_misc/integration_test_models_instance1/transcript_count.json index 65a297e9..585f70ff 100644 --- a/test/integration_test_misc/integration_test_models_instance1/transcript_count.json +++ b/test/integration_test_misc/integration_test_models_instance1/transcript_count.json @@ -1,28 +1,30 @@ { - "model" : "transcript_count", - "storageType" : "SQL", - "attributes" : { - "gene" : "String", - "variable" : "String", - "count" : "Float", + "model": "transcript_count", + "storageType": "SQL", + "attributes": { + "gene": "String", + "variable": "String", + "count": "Float", "tissue_or_condition": "String", "individual_id": "Int", "aminoacidsequence_id": "Int" }, - "associations":{ - "individual":{ - "type" : "to_one", - "target" : "individual", - "targetKey" : "individual_id", + "associations": { + "individual": { + "type": "many_to_one", + "implementation": "foreignkey", + "target": "individual", + "targetKey": "individual_id", "keyIn": "transcript_count", - "targetStorageType" : "sql" + "targetStorageType": "sql" }, - "aminoacidsequence":{ - "type" : "to_one", - "target" : "aminoacidsequence", - "targetKey" : "aminoacidsequence_id", + "aminoacidsequence": { + "type": "many_to_one", + "implementation": "foreignkey", + "target": "aminoacidsequence", + "targetKey": "aminoacidsequence_id", "keyIn": "transcript_count", - "targetStorageType" : "generic" + "targetStorageType": "generic" } } } diff --git a/test/integration_test_misc/integration_test_models_instance2/accession.json b/test/integration_test_misc/integration_test_models_instance2/accession.json index 14de440d..191dcc94 100644 --- a/test/integration_test_misc/integration_test_models_instance2/accession.json +++ b/test/integration_test_misc/integration_test_models_instance2/accession.json @@ -13,24 +13,25 @@ "associations": { "location": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Location", "targetKey": "locationId", - "keyIn" : "Accession", + "keyIn": "Accession", "targetStorageType": "sql", "label": "country", "sublabel": "state" }, "measurements": { - "type": "to_many", + "type": "one_to_many", "target": "Measurement", "targetKey": "accessionId", - "keyIn" : "Measurement", + "keyIn": "Measurement", "targetStorageType": "sql", "label": "name" } }, - "internalId" : "accession_id" + "internalId": "accession_id" } diff --git a/test/integration_test_misc/integration_test_models_instance2/author.json b/test/integration_test_misc/integration_test_models_instance2/author.json index 9e8d3904..c652a3d9 100644 --- a/test/integration_test_misc/integration_test_models_instance2/author.json +++ b/test/integration_test_misc/integration_test_models_instance2/author.json @@ -1,8 +1,8 @@ { - "model" : "author", - "storageType" : "zendro-server", + "model": "author", + "storageType": "zendro-server", "url": "http://server1:3000/graphql", - "attributes" : { + "attributes": { "id": "String", "name": "String", "lastname": "String", @@ -12,8 +12,7 @@ "associations":{ "books":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", "target": "book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/book.json b/test/integration_test_misc/integration_test_models_instance2/book.json index f8cdf101..24427e9f 100644 --- a/test/integration_test_misc/integration_test_models_instance2/book.json +++ b/test/integration_test_misc/integration_test_models_instance2/book.json @@ -1,8 +1,8 @@ { - "model" : "book", - "storageType" : "zendro-server", + "model": "book", + "storageType": "zendro-server", "url": "http://server1:3000/graphql", - "attributes" : { + "attributes": { "id": "String", "title": "String", "genre": "String", @@ -12,8 +12,7 @@ "associations":{ "authors":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", "target": "author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/dist_presto_doctor.json b/test/integration_test_misc/integration_test_models_instance2/dist_presto_doctor.json index 116062c8..8339a2e5 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dist_presto_doctor.json +++ b/test/integration_test_misc/integration_test_models_instance2/dist_presto_doctor.json @@ -1,6 +1,6 @@ { "model": "dist_presto_doctor", - "storageType" : "distributed-data-model", + "storageType": "distributed-data-model", "registry": ["dist_presto_doctor_instance1"], "attributes": { "doctor_id": "String", @@ -12,5 +12,5 @@ "telephone": "[Int]" }, - "internalId" : "doctor_id" + "internalId": "doctor_id" } \ No newline at end of file diff --git a/test/integration_test_misc/integration_test_models_instance2/dist_trino_doctor.json b/test/integration_test_misc/integration_test_models_instance2/dist_trino_doctor.json index 3d4815aa..29993258 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dist_trino_doctor.json +++ b/test/integration_test_misc/integration_test_models_instance2/dist_trino_doctor.json @@ -1,6 +1,6 @@ { "model": "dist_trino_doctor", - "storageType" : "distributed-data-model", + "storageType": "distributed-data-model", "registry": ["dist_trino_doctor_instance1"], "attributes": { "doctor_id": "String", @@ -12,5 +12,5 @@ "telephone": "[Int]" }, - "internalId" : "doctor_id" + "internalId": "doctor_id" } \ No newline at end of file diff --git a/test/integration_test_misc/integration_test_models_instance2/dog.json b/test/integration_test_misc/integration_test_models_instance2/dog.json index a0327b87..039b4204 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dog.json +++ b/test/integration_test_misc/integration_test_models_instance2/dog.json @@ -1,19 +1,20 @@ { - "model" : "dog", - "storageType" : "distributed-data-model", + "model": "dog", + "storageType": "distributed-data-model", "registry": ["dog_instance1", "dog_instance2"], - "attributes" : { - "name": "String", + "attributes": { + "name": "String", "dog_id": "String", "person_id": "String" }, "associations": { "person": { - "type" : "to_one", - "target" : "person", - "targetKey" : "person_id", + "type": "many_to_one", + "implementation": "foreignkey", + "target": "person", + "targetKey": "person_id", "keyIn": "dog", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "dog_id" diff --git a/test/integration_test_misc/integration_test_models_instance2/dog_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance2/dog_instance1_adapter.json index 5515ae55..5154c695 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dog_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/dog_instance1_adapter.json @@ -1,21 +1,22 @@ { - "model" : "dog", - "storageType" : "ddm-adapter", + "model": "dog", + "storageType": "ddm-adapter", "adapterName": "dog_instance1", "regex": "instance1", "url": "http://server1:3000/graphql", - "attributes" : { - "name": "String", + "attributes": { + "name": "String", "dog_id": "String", "person_id": "String" }, "associations": { "person": { - "type" : "to_one", - "target" : "person", - "targetKey" : "person_id", + "type": "many_to_one", + "implementation": "foreignkey", + "target": "person", + "targetKey": "person_id", "keyIn": "dog", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "dog_id" diff --git a/test/integration_test_misc/integration_test_models_instance2/dog_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance2/dog_instance2_adapter.json index 1526a9ca..c6680f27 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dog_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/dog_instance2_adapter.json @@ -1,20 +1,21 @@ { - "model" : "dog", - "storageType" : "sql-adapter", + "model": "dog", + "storageType": "sql-adapter", "adapterName": "dog_instance2", "regex": "instance2", - "attributes" : { - "name": "String", + "attributes": { + "name": "String", "dog_id": "String", "person_id": "String" }, "associations": { "person": { - "type" : "to_one", - "target" : "person", - "targetKey" : "person_id", + "type": "many_to_one", + "implementation": "foreignkey", + "target": "person", + "targetKey": "person_id", "keyIn": "dog", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "dog_id" diff --git a/test/integration_test_misc/integration_test_models_instance2/location.json b/test/integration_test_misc/integration_test_models_instance2/location.json index b20b1c1a..e7e87e42 100644 --- a/test/integration_test_misc/integration_test_models_instance2/location.json +++ b/test/integration_test_misc/integration_test_models_instance2/location.json @@ -2,7 +2,7 @@ "model": "Location", "storageType": "zendro-server", "url": "http://server1:3000/graphql", - "attributes" : { + "attributes": { "locationId": "String", "country": "String", "state": "String", @@ -13,7 +13,7 @@ "associations" :{ "accessions": { - "type": "to_many", + "type": "one_to_many", "target": "Accession", "targetKey": "locationId", "keyIn": "Accession", @@ -22,6 +22,6 @@ } }, - "internalId" : "locationId" + "internalId": "locationId" } diff --git a/test/integration_test_misc/integration_test_models_instance2/measurement.json b/test/integration_test_misc/integration_test_models_instance2/measurement.json index c44be5a2..390a55b3 100644 --- a/test/integration_test_misc/integration_test_models_instance2/measurement.json +++ b/test/integration_test_misc/integration_test_models_instance2/measurement.json @@ -12,14 +12,15 @@ "associations": { "accession": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkey", "target": "Accession", "targetKey": "accessionId", - "keyIn" : "Measurement", + "keyIn": "Measurement", "targetStorageType": "sql", "label": "accession_id" } }, - "internalId" : "measurement_id" + "internalId": "measurement_id" } diff --git a/test/integration_test_misc/integration_test_models_instance2/parrot.json b/test/integration_test_misc/integration_test_models_instance2/parrot.json index f838bd00..e73d1d99 100644 --- a/test/integration_test_misc/integration_test_models_instance2/parrot.json +++ b/test/integration_test_misc/integration_test_models_instance2/parrot.json @@ -1,19 +1,20 @@ { - "model" : "parrot", - "storageType" : "distributed-data-model", + "model": "parrot", + "storageType": "distributed-data-model", "registry": ["parrot_instance1", "parrot_instance2"], - "attributes" : { - "name" : "String", + "attributes": { + "name": "String", "parrot_id": "String", "person_id": "String" }, "associations": { "unique_person": { - "type" : "to_one", - "target" : "person", - "targetKey" : "person_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "person", + "targetKey": "person_id", "keyIn": "parrot", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "parrot_id" diff --git a/test/integration_test_misc/integration_test_models_instance2/parrot_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance2/parrot_instance1_adapter.json index 4d0b8aad..0e6acd23 100644 --- a/test/integration_test_misc/integration_test_models_instance2/parrot_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/parrot_instance1_adapter.json @@ -1,21 +1,22 @@ { - "model" : "parrot", - "storageType" : "ddm-adapter", + "model": "parrot", + "storageType": "ddm-adapter", "adapterName": "parrot_instance1", "regex": "instance1", "url": "http://server1:3000/graphql", - "attributes" : { - "name" : "String", + "attributes": { + "name": "String", "parrot_id": "String", "person_id": "String" }, "associations": { "unique_person": { - "type" : "to_one", - "target" : "person", - "targetKey" : "person_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "person", + "targetKey": "person_id", "keyIn": "parrot", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "parrot_id" diff --git a/test/integration_test_misc/integration_test_models_instance2/parrot_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance2/parrot_instance2_adapter.json index d099d1ea..bf9fa55f 100644 --- a/test/integration_test_misc/integration_test_models_instance2/parrot_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/parrot_instance2_adapter.json @@ -1,20 +1,21 @@ { - "model" : "parrot", - "storageType" : "sql-adapter", + "model": "parrot", + "storageType": "sql-adapter", "adapterName": "parrot_instance2", "regex": "instance2", - "attributes" : { - "name" : "String", + "attributes": { + "name": "String", "parrot_id": "String", "person_id": "String" }, "associations": { "unique_person": { - "type" : "to_one", - "target" : "person", - "targetKey" : "person_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "person", + "targetKey": "person_id", "keyIn": "parrot", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "parrot_id" diff --git a/test/integration_test_misc/integration_test_models_instance2/person.json b/test/integration_test_misc/integration_test_models_instance2/person.json index adc5cbe5..45c43f05 100644 --- a/test/integration_test_misc/integration_test_models_instance2/person.json +++ b/test/integration_test_misc/integration_test_models_instance2/person.json @@ -1,25 +1,26 @@ { - "model" : "person", - "storageType" : "distributed-data-model", + "model": "person", + "storageType": "distributed-data-model", "registry": ["person_instance1", "person_instance2"], - "attributes" : { - "name" : "String", + "attributes": { + "name": "String", "person_id": "String" }, "associations": { "dogs": { - "type" : "to_many", - "target" : "dog", - "targetKey" : "person_id", + "type": "one_to_many", + "target": "dog", + "targetKey": "person_id", "keyIn": "dog", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" }, "unique_parrot": { - "type" : "to_one", - "target" : "parrot", - "targetKey" : "person_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "parrot", + "targetKey": "person_id", "keyIn": "parrot", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "person_id" diff --git a/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json index eb908d1e..089bb3c6 100644 --- a/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json @@ -1,27 +1,28 @@ { - "model" : "person", - "storageType" : "ddm-adapter", + "model": "person", + "storageType": "ddm-adapter", "adapterName": "person_instance1", "regex": "instance1", "url": "http://server1:3000/graphql", - "attributes" : { - "name" : "String", + "attributes": { + "name": "String", "person_id": "String" }, "associations": { "dogs": { - "type" : "to_many", - "target" : "dog", - "targetKey" : "person_id", + "type": "one_to_many", + "target": "dog", + "targetKey": "person_id", "keyIn": "dog", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" }, "unique_parrot": { - "type" : "to_one", - "target" : "parrot", - "targetKey" : "person_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "parrot", + "targetKey": "person_id", "keyIn": "parrot", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "person_id" diff --git a/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json index a4ef9421..7b9a29fc 100644 --- a/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json @@ -1,26 +1,27 @@ { - "model" : "person", - "storageType" : "sql-adapter", + "model": "person", + "storageType": "sql-adapter", "adapterName": "person_instance2", "regex": "instance2", - "attributes" : { - "name" : "String", + "attributes": { + "name": "String", "person_id": "String" }, "associations": { "dogs": { - "type" : "to_many", - "target" : "dog", - "targetKey" : "person_id", + "type": "one_to_many", + "target": "dog", + "targetKey": "person_id", "keyIn": "dog", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" }, "unique_parrot": { - "type" : "to_one", - "target" : "parrot", - "targetKey" : "person_id", + "type": "one_to_one", + "implementation": "foreignkey", + "target": "parrot", + "targetKey": "person_id", "keyIn": "parrot", - "targetStorageType" : "distributed-data-model" + "targetStorageType": "distributed-data-model" } }, "internalId": "person_id" diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json index f7bd485c..dd884f38 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json @@ -1,9 +1,9 @@ { - "model" : "sq_author", - "storageType" : "sql-adapter", + "model": "sq_author", + "storageType": "sql-adapter", "adapterName": "author_local", "regex": "local", - "attributes" : { + "attributes": { "id": "String", "name": "String", "lastname": "String", @@ -13,8 +13,7 @@ "associations":{ "books":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json b/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json index 2e6c8655..121e82f0 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json @@ -1,8 +1,8 @@ { - "model" : "sq_author", - "storageType" : "distributed-data-model", + "model": "sq_author", + "storageType": "distributed-data-model", "registry": ["author_remote","author_local"], - "attributes" : { + "attributes": { "id": "String", "name": "String", "lastname": "String", @@ -12,8 +12,7 @@ "associations":{ "books":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json index d3cc230f..b9bfc665 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json @@ -1,10 +1,10 @@ { - "model" : "sq_author", - "storageType" : "zendro-webservice-adapter", + "model": "sq_author", + "storageType": "zendro-webservice-adapter", "adapterName": "author_remote", "regex": "remote", "url": "http://server1:3000/graphql", - "attributes" : { + "attributes": { "id": "String", "name": "String", "lastname": "String", @@ -14,8 +14,7 @@ "associations":{ "books":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json index d6d8a44a..f908a3ee 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json @@ -1,9 +1,9 @@ { - "model" : "sq_book", - "storageType" : "sql-adapter", + "model": "sq_book", + "storageType": "sql-adapter", "adapterName": "book_local", "regex": "local", - "attributes" : { + "attributes": { "id": "String", "title": "String", "genre": "String", @@ -13,8 +13,7 @@ "associations":{ "authors":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json b/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json index e93f0bbd..0e84f453 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json @@ -1,8 +1,8 @@ { - "model" : "sq_book", - "storageType" : "distributed-data-model", + "model": "sq_book", + "storageType": "distributed-data-model", "registry": ["book_remote","book_local"], - "attributes" : { + "attributes": { "id": "String", "title": "String", "genre": "String", @@ -12,8 +12,7 @@ "associations":{ "authors":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json index 430606da..1abeb828 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json @@ -1,10 +1,10 @@ { - "model" : "sq_book", - "storageType" : "zendro-webservice-adapter", + "model": "sq_book", + "storageType": "zendro-webservice-adapter", "adapterName": "book_remote", "regex": "remote", "url": "http://server1:3000/graphql", - "attributes" : { + "attributes": { "id": "String", "title": "String", "genre": "String", @@ -14,8 +14,7 @@ "associations":{ "authors":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", From 599c1c97fdeda48ff01dd211206b7dca3ab481ed Mon Sep 17 00:00:00 2001 From: coeit Date: Tue, 8 Jun 2021 18:51:55 +0200 Subject: [PATCH 04/18] fix: add missing implementation types --- .../integration_test_models_instance2/accession.json | 1 + .../integration_test_models_instance2/author.json | 1 + .../integration_test_models_instance2/book.json | 1 + .../integration_test_models_instance2/location.json | 1 + .../integration_test_models_instance2/person.json | 1 + .../person_instance1_adapter.json | 1 + .../person_instance2_adapter.json | 1 + .../integration_test_models_instance2/sq_author_adapter.json | 1 + .../integration_test_models_instance2/sq_author_ddm.json | 1 + .../sq_author_zendro_adapter.json | 1 + .../integration_test_models_instance2/sq_book_adapter.json | 1 + .../integration_test_models_instance2/sq_book_ddm.json | 1 + .../sq_book_zendro_adapter.json | 1 + 13 files changed, 13 insertions(+) diff --git a/test/integration_test_misc/integration_test_models_instance2/accession.json b/test/integration_test_misc/integration_test_models_instance2/accession.json index 191dcc94..9f3b0f7e 100644 --- a/test/integration_test_misc/integration_test_models_instance2/accession.json +++ b/test/integration_test_misc/integration_test_models_instance2/accession.json @@ -25,6 +25,7 @@ "measurements": { "type": "one_to_many", + "implementation": "foreignkey", "target": "Measurement", "targetKey": "accessionId", "keyIn": "Measurement", diff --git a/test/integration_test_misc/integration_test_models_instance2/author.json b/test/integration_test_misc/integration_test_models_instance2/author.json index c652a3d9..380630c7 100644 --- a/test/integration_test_misc/integration_test_models_instance2/author.json +++ b/test/integration_test_misc/integration_test_models_instance2/author.json @@ -13,6 +13,7 @@ "associations":{ "books":{ "type": "many_to_many", + "implementation": "foreignkey", "target": "book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/book.json b/test/integration_test_misc/integration_test_models_instance2/book.json index 24427e9f..6e75e12c 100644 --- a/test/integration_test_misc/integration_test_models_instance2/book.json +++ b/test/integration_test_misc/integration_test_models_instance2/book.json @@ -13,6 +13,7 @@ "associations":{ "authors":{ "type": "many_to_many", + "implementation": "foreignkey", "target": "author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/location.json b/test/integration_test_misc/integration_test_models_instance2/location.json index e7e87e42..16ec224a 100644 --- a/test/integration_test_misc/integration_test_models_instance2/location.json +++ b/test/integration_test_misc/integration_test_models_instance2/location.json @@ -14,6 +14,7 @@ "accessions": { "type": "one_to_many", + "implementation": "foreignkey", "target": "Accession", "targetKey": "locationId", "keyIn": "Accession", diff --git a/test/integration_test_misc/integration_test_models_instance2/person.json b/test/integration_test_misc/integration_test_models_instance2/person.json index 45c43f05..5da3badd 100644 --- a/test/integration_test_misc/integration_test_models_instance2/person.json +++ b/test/integration_test_misc/integration_test_models_instance2/person.json @@ -9,6 +9,7 @@ "associations": { "dogs": { "type": "one_to_many", + "implementation": "foreignkey", "target": "dog", "targetKey": "person_id", "keyIn": "dog", diff --git a/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json index 089bb3c6..3793947a 100644 --- a/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json @@ -11,6 +11,7 @@ "associations": { "dogs": { "type": "one_to_many", + "implementation": "foreignkey", "target": "dog", "targetKey": "person_id", "keyIn": "dog", diff --git a/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json index 7b9a29fc..76ebd155 100644 --- a/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json @@ -10,6 +10,7 @@ "associations": { "dogs": { "type": "one_to_many", + "implementation": "foreignkey", "target": "dog", "targetKey": "person_id", "keyIn": "dog", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json index dd884f38..032d0e34 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json @@ -14,6 +14,7 @@ "associations":{ "books":{ "type": "many_to_many", + "implementation": "foreignkey", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json b/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json index 121e82f0..f6e97935 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json @@ -13,6 +13,7 @@ "associations":{ "books":{ "type": "many_to_many", + "implementation": "foreignkey", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json index b9bfc665..6dd5592e 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json @@ -15,6 +15,7 @@ "associations":{ "books":{ "type": "many_to_many", + "implementation": "foreignkey", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json index f908a3ee..05a9f050 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json @@ -14,6 +14,7 @@ "associations":{ "authors":{ "type": "many_to_many", + "implementation": "foreignkey", "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json b/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json index 0e84f453..40a02cf1 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json @@ -13,6 +13,7 @@ "associations":{ "authors":{ "type": "many_to_many", + "implementation": "foreignkey", "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json index 1abeb828..5724e29b 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json @@ -15,6 +15,7 @@ "associations":{ "authors":{ "type": "many_to_many", + "implementation": "foreignkey", "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", From 2a87d806eb15c29eb651d81f3b0e14dd7d754202 Mon Sep 17 00:00:00 2001 From: coeit Date: Wed, 9 Jun 2021 17:37:50 +0200 Subject: [PATCH 05/18] refactor: add "reverseAssociation" field to association definition --- funks.js | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/funks.js b/funks.js index 1b4ad97d..4efa1d23 100644 --- a/funks.js +++ b/funks.js @@ -656,15 +656,34 @@ validateJsonFile = function (opts) { } }); - //check: validate if to_one assoc with foreignKey in target model exists - // Warn user that validation e.g. unique constraint needs to be added - opts.associationsArguments["to_one"].forEach((assoc) => { - if (assoc.holdsForeignKey === false) { + const { + to_one, + to_many, + to_many_through_sql_cross_table, + generic_to_one, + generic_to_many } = opts.associationsArguments; + + const parsedAssociations = to_one.concat(to_many,to_many_through_sql_cross_table, generic_to_many, generic_to_one); + + parsedAssociations.forEach((assoc) => { + + //check: validate if to_one assoc with foreignKey in target model exists + // Warn user that validation e.g. unique constraint needs to be added + if (assoc.holdsForeignKey === false && assoc.type.includes('to_one')) { check.warnings.push( - `WARNING: ${assoc.name} is a to_one associations with the foreignKey in ${assoc.target}. Be sure to validate uniqueness` + `WARNING: Association ${assoc.name} is a ${assoc.type} associations with the foreignKey in ${assoc.target}. Be sure to validate uniqueness` ); } - }); + + //check: validate if the reverseAssociation field exist. Warn the user that + // it is mandatory for the spa + if (!assoc.reverseAssociation) { + check.warnings.push( + ` WARNING: Association ${assoc.name} does not define the reverse association name in field "reverseAssociation". This field is mandatory for the single-page-app.` + ) + } + }) + return check; }; @@ -742,8 +761,6 @@ module.exports.parseAssociations = function (dataModel) { capitalizeString(association.target), capitalizeString(name), ]; - let holdsTheForeignKey = false; - let assocThroughArray = false; let assoc = Object.assign({}, association); if (type !== 'one_to_one' && type !== 'one_to_many' && type !== 'many_to_one' && type !== 'many_to_many') { @@ -765,6 +782,7 @@ module.exports.parseAssociations = function (dataModel) { assoc["target_cp_pl"] = capitalizeString( inflection.pluralize(association.target) ); + assoc["reverseAssociation"] = association.reverseAssociation; if (implementation !== 'generic') { // set extra association fields @@ -783,7 +801,6 @@ module.exports.parseAssociations = function (dataModel) { } else { associations_info.genericAssociations.push(association); } - // switch implementation types switch (implementation) { case 'generic': @@ -860,7 +877,6 @@ module.exports.parseAssociations = function (dataModel) { associations_info.mutations_attributes = attributesToString( associations_info.mutations_attributes ); - // console.log(JSON.stringify(associations_info,null,2)); return associations_info; }; From 99b0ad6bd00ba66fb57af03dc93d8500f8337de4 Mon Sep 17 00:00:00 2001 From: coeit Date: Wed, 9 Jun 2021 17:38:13 +0200 Subject: [PATCH 06/18] fix: unit tests - add reverseAssociation --- test/mocha_unit.test.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/mocha_unit.test.js b/test/mocha_unit.test.js index d2e71bce..8f08be26 100644 --- a/test/mocha_unit.test.js +++ b/test/mocha_unit.test.js @@ -1373,6 +1373,7 @@ describe("Parse associations", function () { keyIn_lc: "transcript_count", holdsForeignKey: true, assocThroughArray: false, + reverseAssociation: undefined, }, ], to_many: [], @@ -1433,6 +1434,7 @@ describe("Parse associations", function () { keyIn_lc: "transcript_count", holdsForeignKey: false, assocThroughArray: false, + reverseAssociation: undefined, }, ], to_many_through_sql_cross_table: [], @@ -1493,6 +1495,7 @@ describe("Parse associations", function () { name_cp: "Assoc", holdsForeignKey: false, assocThroughArray: false, + reverseAssociation: undefined, }, ], generic_to_one: [], @@ -1557,6 +1560,7 @@ describe("Parse associations", function () { keyIn_lc: "dog", holdsForeignKey: false, assocThroughArray: false, + reverseAssociation: undefined, }, ], to_many_through_sql_cross_table: [ @@ -1579,6 +1583,7 @@ describe("Parse associations", function () { target_cp_pl: "Books", holdsForeignKey: false, assocThroughArray: false, + reverseAssociation: undefined, }, ], generic_to_one: [], @@ -1645,6 +1650,7 @@ describe("Parse associations", function () { keyIn_lc: "dog", holdsForeignKey: true, assocThroughArray: false, + reverseAssociation: undefined, }, { type: "many_to_one", @@ -1666,6 +1672,7 @@ describe("Parse associations", function () { keyIn_lc: "dog", holdsForeignKey: true, assocThroughArray: false, + reverseAssociation: undefined, }, ], to_many: [], From 551b1f6135bd61db90a330daa163b9d33413461f Mon Sep 17 00:00:00 2001 From: coeit Date: Thu, 10 Jun 2021 10:45:12 +0200 Subject: [PATCH 07/18] refactor: update README for new association types --- README.md | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 11714bbe..f4d0295f 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,9 @@ EXAMPLES OF VALID JSON FILES "associations" : { "person" : { - "type" : "to_one", + "type" : "many_to_one", + "implementation": "foreignkey", + "reverseAssociation": "dogs", "target" : "Person", "targetKey" : "personId", "keyIn": "Dog", @@ -119,7 +121,9 @@ EXAMPLES OF VALID JSON FILES }, "associations":{ "books" : { - "type" : "to_many", + "type" : "one_to_many", + "implementation": "foreignkey", + "reverseAssociation": "publisher", "target" : "Book", "targetKey" : "publisherId", "keyIn" : "Book", @@ -153,16 +157,19 @@ Example: ### Associations Spec -We will consider two types of associations accordingly to the number of records -that can posibly be associated: -1. to_one -2. to_many +We will consider four types of associations according to the relation between associated records of the two models: +1. one_to_one +2. many_to_one +3. one_to_many +4. many_to_many For both type of association, the necessary arguments would be: name | Type | Description ------- | ------- | -------------- -*type* | String | Type of association (like belongsTo, etc.) +*type* | String | Type of association (`one_to_one`, `one_to_many`, etc.) +*implementation* | String | implementation type of the association. Can be one of `foreignkey`, `generic` or `sql_cross_table` (only for `many_to_many`)` +*reverseAssociation* | String | The name of the reverse association from the other model. This field is only mandatory for building the [single-page-app](https://github.com/Zendro-dev/single-page-app), *not* for generating the the graphql-server code via this repository. *target* | String | Name of model to which the current model will be associated with. *targetKey* | String | A unique identifier of the association for the case where there appear more than one association with the same model. *keyIn* | String | Name of the model where the targetKey is stored. @@ -170,7 +177,7 @@ name | Type | Description *label* | String | Name of the column in the target model to be used as a display name in the GUI. *sublabel* | String | Optional name of the column in the target model to be used as a sub-label in the GUI. -When the association is of type *to_many* and it referes to a more particular type of association *many_to_many* it's necessary to describe two extra arguments given that the association is made with a cross table. These arguments are: +When the association is of type *many_to_many* it's necessary to describe two extra arguments given that the association is made with a cross table. These arguments are: name | Type | Description ------- | ------- | -------------- @@ -178,7 +185,7 @@ name | Type | Description *keysIn* | String | Name of the cross table ## NOTE: -Be aware that in the case of this type of association the user is required to describe the cross table used in the field _keysIn_ as a model in its own. For example, if we have a model `User` and a model `Role` and they are associated in a _manytomany_ way, then we also need to describe the `role_to_user` model: +Be aware that in the case of this type of association the user is required to describe the cross table used in the field _keysIn_ as a model in its own. For example, if we have a model `User` and a model `Role` and they are associated in a `many_to_many` way, then we also need to describe the `role_to_user` model: ```jsonc //User model @@ -191,7 +198,9 @@ Be aware that in the case of this type of association the user is required to de }, "associations" :{ "roles" : { - "type" : "to_many", + "type" : "many_to_many", + "implementation": "foreignkey", + "reverseAssociation": "dogs", "target" : "Role", "targetKey" : "role_Id", "sourceKey" : "user_Id", @@ -217,6 +226,8 @@ Be aware that in the case of this type of association the user is required to de "users" : { "type" : "to_many", "target" : "User", + "implementation": "sql_cross_table", + "reverseAssociation": "roles", "targetKey" : "user_Id", "sourceKey" : "role_Id", "keysIn" : "role_to_user", @@ -255,10 +266,12 @@ Example: "associations":{ "publisher" : { "type" : "to_one", // association type + "implementation": "foreignkey", // standard implementation via foreign keys + "reverseAssociation": "dogs", // name of the association in the publisher model "target" : "publisher", // Model's name is `publisher` "targetKey" : "publisher_id", // Local alias for this association "keyIn": "book", // FK to publisher will be stored in the Book model - "targetStorageType" : Webservice", // It's a remote database + "targetStorageType" : "Webservice", // It's a remote database "label" : "name" // Show in GUI the name of the publisher taken from external DB } } @@ -276,13 +289,15 @@ Example: "model" : "Book", "storageType" : "SQL", "attributes" : { - "id" : Int, + "id" : "Int", "title" : {"type":"String", "description": "The book's title"}, - "ISBN": Int + "ISBN": "Int" }, "associations" : { "authors" : { - "type" : "to_many", + "type" : "many_to_many", + "implementation": "sql_cross_table", + "reverseAssociation": "books", "target" : "Person", "targetKey" : "person_id", "sourceKey" : "book_id", From cf295e700533d4d66c794669c4882e52bb145c44 Mon Sep 17 00:00:00 2001 From: coeit Date: Thu, 10 Jun 2021 16:43:20 +0200 Subject: [PATCH 08/18] refactor: remove check for targetStorageType on sql_cross_table implementation --- funks.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/funks.js b/funks.js index 4efa1d23..3f09ff2c 100644 --- a/funks.js +++ b/funks.js @@ -822,8 +822,7 @@ module.exports.parseAssociations = function (dataModel) { case 'sql_cross_table': if (type !== 'many_to_many' || association.sourceKey === undefined - || association.keysIn === undefined - || association.targetStorageType !== "sql" ) { + || association.keysIn === undefined ) { console.error( colors.red( `ERROR: many_to_many through crosstable only allowed for relational database types with well defined cross-table` From ceb307ffa8cffadac0c4253d8cfbd7a2f44efd17 Mon Sep 17 00:00:00 2001 From: coeit Date: Thu, 10 Jun 2021 16:54:46 +0200 Subject: [PATCH 09/18] refactor: always use "keysIn" instead of "keyIn" / "keysIn" --- README.md | 8 +-- funks.js | 10 +-- .../accession.json | 4 +- .../amino_acid_sequence.json | 2 +- .../animal.json | 6 +- .../author.json | 2 +- .../book.json | 2 +- .../capital.json | 4 +- .../cassandra-city.json | 2 +- .../cassandra-incident.json | 4 +- .../cassandra-instant.json | 2 +- .../country.json | 2 +- .../dist_animal.json | 2 +- .../dist_animal_instance1.json | 2 +- .../dist_farm.json | 2 +- .../dist_farm_instance1.json | 2 +- .../dist_incident.json | 2 +- .../dist_incident_instance1.json | 2 +- .../dist_instant.json | 2 +- .../dist_instant_instance1.json | 2 +- .../dog.json | 2 +- .../dog_instance1_adapter.json | 2 +- .../dog_instance2_adapter.json | 2 +- .../farm.json | 2 +- .../food.json | 2 +- .../individual.json | 2 +- .../location.json | 2 +- .../measurement.json | 2 +- .../parrot.json | 2 +- .../parrot_instance1_adapter.json | 2 +- .../parrot_instance2_adapter.json | 2 +- .../person.json | 4 +- .../person_instance1_adapter.json | 4 +- .../person_instance2_adapter.json | 4 +- .../river.json | 2 +- .../sq_author.json | 2 +- .../sq_book.json | 2 +- .../tracker.json | 2 +- .../transcript_count.json | 4 +- .../accession.json | 4 +- .../author.json | 2 +- .../book.json | 2 +- .../dog.json | 2 +- .../dog_instance1_adapter.json | 2 +- .../dog_instance2_adapter.json | 2 +- .../location.json | 2 +- .../measurement.json | 2 +- .../parrot.json | 2 +- .../parrot_instance1_adapter.json | 2 +- .../parrot_instance2_adapter.json | 2 +- .../person.json | 4 +- .../person_instance1_adapter.json | 4 +- .../person_instance2_adapter.json | 4 +- .../sq_author_adapter.json | 2 +- .../sq_author_ddm.json | 2 +- .../sq_author_zendro_adapter.json | 2 +- .../sq_book_adapter.json | 2 +- .../sq_book_ddm.json | 2 +- .../sq_book_zendro_adapter.json | 2 +- test/mocha_unit.test.js | 32 +++++----- test/unit_test_misc/data_models.js | 62 +++++++++---------- test/unit_test_misc/data_models_cassandra.js | 10 +-- .../unit_test_misc/data_models_distributed.js | 20 +++--- test/unit_test_misc/data_models_extendedId.js | 8 +-- test/unit_test_misc/data_models_generic.js | 8 +-- .../data_models_generic_webservice.js | 8 +-- test/unit_test_misc/data_models_mongodb.js | 6 +- .../unit_test_misc/data_models_refactoring.js | 24 +++---- test/unit_test_misc/data_models_zendro.js | 12 ++-- .../test-describe/distributed-models.js | 8 +-- .../test-describe/zendro-servers.js | 2 +- views/create-models.ejs | 6 +- 72 files changed, 183 insertions(+), 181 deletions(-) diff --git a/README.md b/README.md index f4d0295f..5450414a 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ EXAMPLES OF VALID JSON FILES "reverseAssociation": "dogs", "target" : "Person", "targetKey" : "personId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType" : "sql" } } @@ -126,7 +126,7 @@ EXAMPLES OF VALID JSON FILES "reverseAssociation": "publisher", "target" : "Book", "targetKey" : "publisherId", - "keyIn" : "Book", + "keysIn" : "Book", "targetStorageType" : "sql" } } @@ -172,7 +172,7 @@ name | Type | Description *reverseAssociation* | String | The name of the reverse association from the other model. This field is only mandatory for building the [single-page-app](https://github.com/Zendro-dev/single-page-app), *not* for generating the the graphql-server code via this repository. *target* | String | Name of model to which the current model will be associated with. *targetKey* | String | A unique identifier of the association for the case where there appear more than one association with the same model. -*keyIn* | String | Name of the model where the targetKey is stored. +*keysIn* | String | Name of the model where the targetKey is stored. *targetStorageType* | String | Type of storage where the target model is stored. So far can be one of __sql__ or __Webservice__. *label* | String | Name of the column in the target model to be used as a display name in the GUI. *sublabel* | String | Optional name of the column in the target model to be used as a sub-label in the GUI. @@ -270,7 +270,7 @@ Example: "reverseAssociation": "dogs", // name of the association in the publisher model "target" : "publisher", // Model's name is `publisher` "targetKey" : "publisher_id", // Local alias for this association - "keyIn": "book", // FK to publisher will be stored in the Book model + "keysIn": "book", // FK to publisher will be stored in the Book model "targetStorageType" : "Webservice", // It's a remote database "label" : "name" // Show in GUI the name of the publisher taken from external DB } diff --git a/funks.js b/funks.js index 3f09ff2c..68ee494b 100644 --- a/funks.js +++ b/funks.js @@ -691,14 +691,14 @@ validateJsonFile = function (opts) { getEditableAssociations = function (associations) { let editableAssociations = []; associations["to_one"].forEach((association) => { - if (association.keyIn !== association.target) { + if (association.keysIn !== association.target) { editableAssociations.push(association); } }); //for cases many to many through foreignKey array associations["to_many"].forEach((association) => { - if (association.keyIn !== association.target) { + if (association.keysIn !== association.target) { editableAssociations.push(association); } }); @@ -788,8 +788,8 @@ module.exports.parseAssociations = function (dataModel) { // set extra association fields assoc["targetKey"] = association.targetKey; assoc["targetKey_cp"] = capitalizeString(association.targetKey); - if (association.keyIn) { - assoc["keyIn_lc"] = uncapitalizeString(association.keyIn); + if (association.keysIn) { + assoc["keysIn_lc"] = uncapitalizeString(association.keysIn); } assoc["holdsForeignKey"] = false; assoc["assocThroughArray"] = false; @@ -841,7 +841,7 @@ module.exports.parseAssociations = function (dataModel) { // schema attrtibutes associations_info.schema_attributes["one"][name] = schema_attributes; // holds foreignKey ? - if (association.keyIn === dataModel.model) { + if (association.keysIn === dataModel.model) { assoc["holdsForeignKey"] = true; } associations_info['to_one'].push(assoc); diff --git a/test/integration_test_misc/integration_test_models_instance1/accession.json b/test/integration_test_misc/integration_test_models_instance1/accession.json index 5b20b6ff..fcafd2f4 100644 --- a/test/integration_test_misc/integration_test_models_instance1/accession.json +++ b/test/integration_test_misc/integration_test_models_instance1/accession.json @@ -16,7 +16,7 @@ "implementation": "foreignkey", "target": "Location", "targetKey": "locationId", - "keyIn": "Accession", + "keysIn": "Accession", "targetStorageType": "sql", "label": "country", "sublabel": "state" @@ -27,7 +27,7 @@ "implementation": "foreignkey", "target": "Measurement", "targetKey": "accessionId", - "keyIn": "Measurement", + "keysIn": "Measurement", "targetStorageType": "sql", "label": "name" } diff --git a/test/integration_test_misc/integration_test_models_instance1/amino_acid_sequence.json b/test/integration_test_misc/integration_test_models_instance1/amino_acid_sequence.json index 5f175338..71dcd7ac 100644 --- a/test/integration_test_misc/integration_test_models_instance1/amino_acid_sequence.json +++ b/test/integration_test_misc/integration_test_models_instance1/amino_acid_sequence.json @@ -11,7 +11,7 @@ "implementation": "foreignkey", "target": "transcript_count", "targetKey": "aminoacidsequence_id", - "keyIn": "transcript_count", + "keysIn": "transcript_count", "targetStorageType": "sql" } } diff --git a/test/integration_test_misc/integration_test_models_instance1/animal.json b/test/integration_test_misc/integration_test_models_instance1/animal.json index 57ec0db1..c7de2820 100644 --- a/test/integration_test_misc/integration_test_models_instance1/animal.json +++ b/test/integration_test_misc/integration_test_models_instance1/animal.json @@ -19,7 +19,7 @@ "implementation": "foreignkey", "target": "farm", "targetKey": "farm_id", - "keyIn": "animal", + "keysIn": "animal", "targetStorageType": "mongodb", "label": "farm_name" }, @@ -29,7 +29,7 @@ "target": "food", "targetKey": "animal_ids", "sourceKey": "food_ids", - "keyIn": "animal", + "keysIn": "animal", "targetStorageType": "mongodb" }, "unique_tracker": { @@ -37,7 +37,7 @@ "implementation": "foreignkey", "target": "tracker", "targetKey": "animal_id", - "keyIn": "tracker", + "keysIn": "tracker", "targetStorageType": "mongodb" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/author.json b/test/integration_test_misc/integration_test_models_instance1/author.json index 18454f87..6d58dec6 100644 --- a/test/integration_test_misc/integration_test_models_instance1/author.json +++ b/test/integration_test_misc/integration_test_models_instance1/author.json @@ -17,7 +17,7 @@ "target": "book", "targetKey": "author_ids", "sourceKey": "book_ids", - "keyIn": "author", + "keysIn": "author", "targetStorageType": "sql" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/book.json b/test/integration_test_misc/integration_test_models_instance1/book.json index 89054737..0f902024 100644 --- a/test/integration_test_misc/integration_test_models_instance1/book.json +++ b/test/integration_test_misc/integration_test_models_instance1/book.json @@ -17,7 +17,7 @@ "target": "author", "targetKey": "book_ids", "sourceKey": "author_ids", - "keyIn": "book", + "keysIn": "book", "targetStorageType": "sql" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/capital.json b/test/integration_test_misc/integration_test_models_instance1/capital.json index 420c399e..07f1797e 100644 --- a/test/integration_test_misc/integration_test_models_instance1/capital.json +++ b/test/integration_test_misc/integration_test_models_instance1/capital.json @@ -12,7 +12,7 @@ "implementation": "foreignkey", "target": "country", "targetKey": "country_id", - "keyIn": "capital", + "keysIn": "capital", "targetStorageType": "sql" }, "incidents": { @@ -20,7 +20,7 @@ "implementation": "foreignkey", "target": "Incident", "targetKey": "capital_id", - "keyIn": "Incident", + "keysIn": "Incident", "targetStorageType": "cassandra" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/cassandra-city.json b/test/integration_test_misc/integration_test_models_instance1/cassandra-city.json index 1092124b..5e7876c0 100644 --- a/test/integration_test_misc/integration_test_models_instance1/cassandra-city.json +++ b/test/integration_test_misc/integration_test_models_instance1/cassandra-city.json @@ -21,7 +21,7 @@ "targetStorageType": "sql", "sourceKey": "river_ids", "targetKey": "city_ids", - "keyIn": "city" + "keysIn": "city" } }, "internalId": "city_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/cassandra-incident.json b/test/integration_test_misc/integration_test_models_instance1/cassandra-incident.json index e3d66a1d..63ac885b 100644 --- a/test/integration_test_misc/integration_test_models_instance1/cassandra-incident.json +++ b/test/integration_test_misc/integration_test_models_instance1/cassandra-incident.json @@ -15,7 +15,7 @@ "implementation": "foreignkey", "target": "Instant", "targetKey": "incident_assoc_id", - "keyIn": "Instant", + "keysIn": "Instant", "targetStorageType": "cassandra" }, "town": { @@ -23,7 +23,7 @@ "implementation": "foreignkey", "target": "capital", "targetKey": "capital_id", - "keyIn": "Incident", + "keysIn": "Incident", "targetStorageType": "sql" } diff --git a/test/integration_test_misc/integration_test_models_instance1/cassandra-instant.json b/test/integration_test_misc/integration_test_models_instance1/cassandra-instant.json index e1784740..358fe7a7 100644 --- a/test/integration_test_misc/integration_test_models_instance1/cassandra-instant.json +++ b/test/integration_test_misc/integration_test_models_instance1/cassandra-instant.json @@ -18,7 +18,7 @@ "implementation": "foreignkey", "target": "Incident", "targetKey": "incident_assoc_id", - "keyIn": "Instant", + "keysIn": "Instant", "targetStorageType": "cassandra" } diff --git a/test/integration_test_misc/integration_test_models_instance1/country.json b/test/integration_test_misc/integration_test_models_instance1/country.json index 798db811..de25463e 100644 --- a/test/integration_test_misc/integration_test_models_instance1/country.json +++ b/test/integration_test_misc/integration_test_models_instance1/country.json @@ -11,7 +11,7 @@ "implementation": "foreignkey", "target": "capital", "targetKey": "country_id", - "keyIn": "capital", + "keysIn": "capital", "targetStorageType": "sql" }, "rivers": { diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_animal.json b/test/integration_test_misc/integration_test_models_instance1/dist_animal.json index 449488f9..6197981d 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_animal.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_animal.json @@ -20,7 +20,7 @@ "implementation": "foreignkey", "target": "dist_farm", "targetKey": "farm_id", - "keyIn": "dist_animal", + "keysIn": "dist_animal", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_animal_instance1.json b/test/integration_test_misc/integration_test_models_instance1/dist_animal_instance1.json index 3d47488a..18f5cffc 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_animal_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_animal_instance1.json @@ -22,7 +22,7 @@ "implementation": "foreignkey", "target": "dist_farm", "targetKey": "farm_id", - "keyIn": "dist_animal", + "keysIn": "dist_animal", "targetStorageType": "distributed-data-model" } diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_farm.json b/test/integration_test_misc/integration_test_models_instance1/dist_farm.json index 980e4c0d..2ed825a5 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_farm.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_farm.json @@ -13,7 +13,7 @@ "implementation": "foreignkey", "target": "dist_animal", "targetKey": "farm_id", - "keyIn": "dist_animal", + "keysIn": "dist_animal", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_farm_instance1.json b/test/integration_test_misc/integration_test_models_instance1/dist_farm_instance1.json index 6579befc..93d6a8ba 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_farm_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_farm_instance1.json @@ -14,7 +14,7 @@ "implementation": "foreignkey", "target": "dist_animal", "targetKey": "farm_id", - "keyIn": "dist_animal", + "keysIn": "dist_animal", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_incident.json b/test/integration_test_misc/integration_test_models_instance1/dist_incident.json index a7f23958..d1339603 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_incident.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_incident.json @@ -16,7 +16,7 @@ "implementation": "foreignkey", "target": "Dist_instant", "targetKey": "incident_assoc_id", - "keyIn": "Dist_instant", + "keysIn": "Dist_instant", "targetStorageType": "distributed-data-model" } diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_incident_instance1.json b/test/integration_test_misc/integration_test_models_instance1/dist_incident_instance1.json index f7cb81bc..2423430d 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_incident_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_incident_instance1.json @@ -16,7 +16,7 @@ "implementation": "foreignkey", "target": "Dist_instant", "targetKey": "incident_assoc_id", - "keyIn": "Dist_instant", + "keysIn": "Dist_instant", "targetStorageType": "distributed-data-model" } diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_instant.json b/test/integration_test_misc/integration_test_models_instance1/dist_instant.json index 58361e35..be113bec 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_instant.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_instant.json @@ -20,7 +20,7 @@ "implementation": "foreignkey", "target": "Dist_incident", "targetKey": "incident_assoc_id", - "keyIn": "Dist_instant", + "keysIn": "Dist_instant", "targetStorageType": "distributed-data-model" } diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_instant_instance1.json b/test/integration_test_misc/integration_test_models_instance1/dist_instant_instance1.json index 09f4b366..37670d6d 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_instant_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_instant_instance1.json @@ -20,7 +20,7 @@ "implementation": "foreignkey", "target": "Dist_incident", "targetKey": "incident_assoc_id", - "keyIn": "Dist_instant", + "keysIn": "Dist_instant", "targetStorageType": "distributed-data-model" } diff --git a/test/integration_test_misc/integration_test_models_instance1/dog.json b/test/integration_test_misc/integration_test_models_instance1/dog.json index f8a6aadc..1c5211d7 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dog.json +++ b/test/integration_test_misc/integration_test_models_instance1/dog.json @@ -13,7 +13,7 @@ "implementation": "foreignkey", "target": "person", "targetKey": "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/dog_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance1/dog_instance1_adapter.json index da2baaf8..59bf7c4a 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dog_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/dog_instance1_adapter.json @@ -14,7 +14,7 @@ "implementation": "foreignkey", "target": "person", "targetKey": "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/dog_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance1/dog_instance2_adapter.json index c47bb80f..650e1e5e 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dog_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/dog_instance2_adapter.json @@ -15,7 +15,7 @@ "implementation": "foreignkey", "target": "person", "targetKey": "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/farm.json b/test/integration_test_misc/integration_test_models_instance1/farm.json index 7b75047c..1874a691 100644 --- a/test/integration_test_misc/integration_test_models_instance1/farm.json +++ b/test/integration_test_misc/integration_test_models_instance1/farm.json @@ -12,7 +12,7 @@ "implementation": "foreignkey", "target": "animal", "targetKey": "farm_id", - "keyIn": "animal", + "keysIn": "animal", "targetStorageType": "mongodb", "label": "animal_id" } diff --git a/test/integration_test_misc/integration_test_models_instance1/food.json b/test/integration_test_misc/integration_test_models_instance1/food.json index e7bd9c07..02ed169b 100644 --- a/test/integration_test_misc/integration_test_models_instance1/food.json +++ b/test/integration_test_misc/integration_test_models_instance1/food.json @@ -14,7 +14,7 @@ "target": "animal", "targetKey": "food_ids", "sourceKey": "animal_ids", - "keyIn": "food", + "keysIn": "food", "targetStorageType": "mongodb" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/individual.json b/test/integration_test_misc/integration_test_models_instance1/individual.json index 885f95a8..5fb42a13 100644 --- a/test/integration_test_misc/integration_test_models_instance1/individual.json +++ b/test/integration_test_misc/integration_test_models_instance1/individual.json @@ -10,7 +10,7 @@ "implementation": "foreignkey", "target": "transcript_count", "targetKey": "individual_id", - "keyIn": "transcript_count", + "keysIn": "transcript_count", "targetStorageType": "sql" } } diff --git a/test/integration_test_misc/integration_test_models_instance1/location.json b/test/integration_test_misc/integration_test_models_instance1/location.json index ca14b7e5..28b4258c 100644 --- a/test/integration_test_misc/integration_test_models_instance1/location.json +++ b/test/integration_test_misc/integration_test_models_instance1/location.json @@ -16,7 +16,7 @@ "implementation": "foreignkey", "target": "Accession", "targetKey": "locationId", - "keyIn": "Accession", + "keysIn": "Accession", "targetStorageType": "sql", "label": "accession_id" } diff --git a/test/integration_test_misc/integration_test_models_instance1/measurement.json b/test/integration_test_misc/integration_test_models_instance1/measurement.json index 978e0968..9aa42b00 100644 --- a/test/integration_test_misc/integration_test_models_instance1/measurement.json +++ b/test/integration_test_misc/integration_test_models_instance1/measurement.json @@ -15,7 +15,7 @@ "implementation": "foreignkey", "target": "Accession", "targetKey": "accessionId", - "keyIn": "Measurement", + "keysIn": "Measurement", "targetStorageType": "sql", "label": "accession_id" } diff --git a/test/integration_test_misc/integration_test_models_instance1/parrot.json b/test/integration_test_misc/integration_test_models_instance1/parrot.json index e73d1d99..9921ef6a 100644 --- a/test/integration_test_misc/integration_test_models_instance1/parrot.json +++ b/test/integration_test_misc/integration_test_models_instance1/parrot.json @@ -13,7 +13,7 @@ "implementation": "foreignkey", "target": "person", "targetKey": "person_id", - "keyIn": "parrot", + "keysIn": "parrot", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/parrot_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance1/parrot_instance1_adapter.json index 83cc99d1..071738b9 100644 --- a/test/integration_test_misc/integration_test_models_instance1/parrot_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/parrot_instance1_adapter.json @@ -14,7 +14,7 @@ "implementation": "foreignkey", "target": "person", "targetKey": "person_id", - "keyIn": "parrot", + "keysIn": "parrot", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/parrot_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance1/parrot_instance2_adapter.json index 29a9e0ab..a0b76a6d 100644 --- a/test/integration_test_misc/integration_test_models_instance1/parrot_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/parrot_instance2_adapter.json @@ -15,7 +15,7 @@ "implementation": "foreignkey", "target": "person", "targetKey": "person_id", - "keyIn": "parrot", + "keysIn": "parrot", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/person.json b/test/integration_test_misc/integration_test_models_instance1/person.json index 5da3badd..e69a8eae 100644 --- a/test/integration_test_misc/integration_test_models_instance1/person.json +++ b/test/integration_test_misc/integration_test_models_instance1/person.json @@ -12,7 +12,7 @@ "implementation": "foreignkey", "target": "dog", "targetKey": "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType": "distributed-data-model" }, "unique_parrot": { @@ -20,7 +20,7 @@ "implementation": "foreignkey", "target": "parrot", "targetKey": "person_id", - "keyIn": "parrot", + "keysIn": "parrot", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/person_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance1/person_instance1_adapter.json index dfed0f54..bb6369ac 100644 --- a/test/integration_test_misc/integration_test_models_instance1/person_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/person_instance1_adapter.json @@ -13,7 +13,7 @@ "implementation": "foreignkey", "target": "dog", "targetKey": "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType": "distributed-data-model" }, "unique_parrot": { @@ -21,7 +21,7 @@ "implementation": "foreignkey", "target": "parrot", "targetKey": "person_id", - "keyIn": "parrot", + "keysIn": "parrot", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/person_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance1/person_instance2_adapter.json index 5a83cbe3..d0b633ae 100644 --- a/test/integration_test_misc/integration_test_models_instance1/person_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/person_instance2_adapter.json @@ -14,7 +14,7 @@ "implementation": "foreignkey", "target": "dog", "targetKey": "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType": "distributed-data-model" }, "unique_parrot": { @@ -22,7 +22,7 @@ "implementation": "foreignkey", "target": "parrot", "targetKey": "person_id", - "keyIn": "parrot", + "keysIn": "parrot", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/river.json b/test/integration_test_misc/integration_test_models_instance1/river.json index c6dd4aee..62c70d00 100644 --- a/test/integration_test_misc/integration_test_models_instance1/river.json +++ b/test/integration_test_misc/integration_test_models_instance1/river.json @@ -25,7 +25,7 @@ "targetStorageType": "cassandra", "sourceKey": "city_ids", "targetKey": "river_ids", - "keyIn": "river" + "keysIn": "river" } }, "internalId": "river_id" diff --git a/test/integration_test_misc/integration_test_models_instance1/sq_author.json b/test/integration_test_misc/integration_test_models_instance1/sq_author.json index 528284b6..39e33d06 100644 --- a/test/integration_test_misc/integration_test_models_instance1/sq_author.json +++ b/test/integration_test_misc/integration_test_models_instance1/sq_author.json @@ -16,7 +16,7 @@ "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", - "keyIn": "sq_author", + "keysIn": "sq_author", "targetStorageType": "sql" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/sq_book.json b/test/integration_test_misc/integration_test_models_instance1/sq_book.json index a6159372..8d783766 100644 --- a/test/integration_test_misc/integration_test_models_instance1/sq_book.json +++ b/test/integration_test_misc/integration_test_models_instance1/sq_book.json @@ -17,7 +17,7 @@ "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", - "keyIn": "sq_book", + "keysIn": "sq_book", "targetStorageType": "sql" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/tracker.json b/test/integration_test_misc/integration_test_models_instance1/tracker.json index c35a2b9d..95782ad1 100644 --- a/test/integration_test_misc/integration_test_models_instance1/tracker.json +++ b/test/integration_test_misc/integration_test_models_instance1/tracker.json @@ -12,7 +12,7 @@ "implementation": "foreignkey", "target": "animal", "targetKey": "animal_id", - "keyIn": "tracker", + "keysIn": "tracker", "targetStorageType": "mongodb" } }, diff --git a/test/integration_test_misc/integration_test_models_instance1/transcript_count.json b/test/integration_test_misc/integration_test_models_instance1/transcript_count.json index 585f70ff..25be80a8 100644 --- a/test/integration_test_misc/integration_test_models_instance1/transcript_count.json +++ b/test/integration_test_misc/integration_test_models_instance1/transcript_count.json @@ -15,7 +15,7 @@ "implementation": "foreignkey", "target": "individual", "targetKey": "individual_id", - "keyIn": "transcript_count", + "keysIn": "transcript_count", "targetStorageType": "sql" }, "aminoacidsequence": { @@ -23,7 +23,7 @@ "implementation": "foreignkey", "target": "aminoacidsequence", "targetKey": "aminoacidsequence_id", - "keyIn": "transcript_count", + "keysIn": "transcript_count", "targetStorageType": "generic" } } diff --git a/test/integration_test_misc/integration_test_models_instance2/accession.json b/test/integration_test_misc/integration_test_models_instance2/accession.json index 9f3b0f7e..6266e614 100644 --- a/test/integration_test_misc/integration_test_models_instance2/accession.json +++ b/test/integration_test_misc/integration_test_models_instance2/accession.json @@ -17,7 +17,7 @@ "implementation": "foreignkey", "target": "Location", "targetKey": "locationId", - "keyIn": "Accession", + "keysIn": "Accession", "targetStorageType": "sql", "label": "country", "sublabel": "state" @@ -28,7 +28,7 @@ "implementation": "foreignkey", "target": "Measurement", "targetKey": "accessionId", - "keyIn": "Measurement", + "keysIn": "Measurement", "targetStorageType": "sql", "label": "name" } diff --git a/test/integration_test_misc/integration_test_models_instance2/author.json b/test/integration_test_misc/integration_test_models_instance2/author.json index 380630c7..3f1c0fdb 100644 --- a/test/integration_test_misc/integration_test_models_instance2/author.json +++ b/test/integration_test_misc/integration_test_models_instance2/author.json @@ -17,7 +17,7 @@ "target": "book", "targetKey": "author_ids", "sourceKey": "book_ids", - "keyIn": "author", + "keysIn": "author", "targetStorageType": "zendro-server" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/book.json b/test/integration_test_misc/integration_test_models_instance2/book.json index 6e75e12c..471e8c07 100644 --- a/test/integration_test_misc/integration_test_models_instance2/book.json +++ b/test/integration_test_misc/integration_test_models_instance2/book.json @@ -17,7 +17,7 @@ "target": "author", "targetKey": "book_ids", "sourceKey": "author_ids", - "keyIn": "book", + "keysIn": "book", "targetStorageType": "zendro-server" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/dog.json b/test/integration_test_misc/integration_test_models_instance2/dog.json index 039b4204..70227002 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dog.json +++ b/test/integration_test_misc/integration_test_models_instance2/dog.json @@ -13,7 +13,7 @@ "implementation": "foreignkey", "target": "person", "targetKey": "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/dog_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance2/dog_instance1_adapter.json index 5154c695..bfeba25c 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dog_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/dog_instance1_adapter.json @@ -15,7 +15,7 @@ "implementation": "foreignkey", "target": "person", "targetKey": "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/dog_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance2/dog_instance2_adapter.json index c6680f27..1fd8a6c2 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dog_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/dog_instance2_adapter.json @@ -14,7 +14,7 @@ "implementation": "foreignkey", "target": "person", "targetKey": "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/location.json b/test/integration_test_misc/integration_test_models_instance2/location.json index 16ec224a..0afe8ba6 100644 --- a/test/integration_test_misc/integration_test_models_instance2/location.json +++ b/test/integration_test_misc/integration_test_models_instance2/location.json @@ -17,7 +17,7 @@ "implementation": "foreignkey", "target": "Accession", "targetKey": "locationId", - "keyIn": "Accession", + "keysIn": "Accession", "targetStorageType": "sql", "label": "accession_id" } diff --git a/test/integration_test_misc/integration_test_models_instance2/measurement.json b/test/integration_test_misc/integration_test_models_instance2/measurement.json index 390a55b3..bcae417d 100644 --- a/test/integration_test_misc/integration_test_models_instance2/measurement.json +++ b/test/integration_test_misc/integration_test_models_instance2/measurement.json @@ -16,7 +16,7 @@ "implementation": "foreignkey", "target": "Accession", "targetKey": "accessionId", - "keyIn": "Measurement", + "keysIn": "Measurement", "targetStorageType": "sql", "label": "accession_id" } diff --git a/test/integration_test_misc/integration_test_models_instance2/parrot.json b/test/integration_test_misc/integration_test_models_instance2/parrot.json index e73d1d99..9921ef6a 100644 --- a/test/integration_test_misc/integration_test_models_instance2/parrot.json +++ b/test/integration_test_misc/integration_test_models_instance2/parrot.json @@ -13,7 +13,7 @@ "implementation": "foreignkey", "target": "person", "targetKey": "person_id", - "keyIn": "parrot", + "keysIn": "parrot", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/parrot_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance2/parrot_instance1_adapter.json index 0e6acd23..b8d9bc5c 100644 --- a/test/integration_test_misc/integration_test_models_instance2/parrot_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/parrot_instance1_adapter.json @@ -15,7 +15,7 @@ "implementation": "foreignkey", "target": "person", "targetKey": "person_id", - "keyIn": "parrot", + "keysIn": "parrot", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/parrot_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance2/parrot_instance2_adapter.json index bf9fa55f..bed23c26 100644 --- a/test/integration_test_misc/integration_test_models_instance2/parrot_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/parrot_instance2_adapter.json @@ -14,7 +14,7 @@ "implementation": "foreignkey", "target": "person", "targetKey": "person_id", - "keyIn": "parrot", + "keysIn": "parrot", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/person.json b/test/integration_test_misc/integration_test_models_instance2/person.json index 5da3badd..e69a8eae 100644 --- a/test/integration_test_misc/integration_test_models_instance2/person.json +++ b/test/integration_test_misc/integration_test_models_instance2/person.json @@ -12,7 +12,7 @@ "implementation": "foreignkey", "target": "dog", "targetKey": "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType": "distributed-data-model" }, "unique_parrot": { @@ -20,7 +20,7 @@ "implementation": "foreignkey", "target": "parrot", "targetKey": "person_id", - "keyIn": "parrot", + "keysIn": "parrot", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json index 3793947a..4f5e1c04 100644 --- a/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json @@ -14,7 +14,7 @@ "implementation": "foreignkey", "target": "dog", "targetKey": "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType": "distributed-data-model" }, "unique_parrot": { @@ -22,7 +22,7 @@ "implementation": "foreignkey", "target": "parrot", "targetKey": "person_id", - "keyIn": "parrot", + "keysIn": "parrot", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json index 76ebd155..f81e380b 100644 --- a/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json @@ -13,7 +13,7 @@ "implementation": "foreignkey", "target": "dog", "targetKey": "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType": "distributed-data-model" }, "unique_parrot": { @@ -21,7 +21,7 @@ "implementation": "foreignkey", "target": "parrot", "targetKey": "person_id", - "keyIn": "parrot", + "keysIn": "parrot", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json index 032d0e34..7716d330 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json @@ -18,7 +18,7 @@ "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", - "keyIn": "sq_author", + "keysIn": "sq_author", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json b/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json index f6e97935..cd6b4353 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json @@ -17,7 +17,7 @@ "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", - "keyIn": "sq_author", + "keysIn": "sq_author", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json index 6dd5592e..0b09df09 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json @@ -19,7 +19,7 @@ "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", - "keyIn": "sq_author", + "keysIn": "sq_author", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json index 05a9f050..c7cb140b 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json @@ -18,7 +18,7 @@ "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", - "keyIn": "sq_book", + "keysIn": "sq_book", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json b/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json index 40a02cf1..3115986c 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json @@ -17,7 +17,7 @@ "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", - "keyIn": "sq_book", + "keysIn": "sq_book", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json index 5724e29b..bd83300a 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json @@ -19,7 +19,7 @@ "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", - "keyIn": "sq_book", + "keysIn": "sq_book", "targetStorageType": "distributed-data-model" } }, diff --git a/test/mocha_unit.test.js b/test/mocha_unit.test.js index 8f08be26..9eb3c6a4 100644 --- a/test/mocha_unit.test.js +++ b/test/mocha_unit.test.js @@ -1360,7 +1360,7 @@ describe("Parse associations", function () { target: "individual", targetKey: "individual_id", targetKey_cp: "Individual_id", - keyIn: "transcript_count", + keysIn: "transcript_count", targetStorageType: "sql", name: "individual", name_lc: "individual", @@ -1370,7 +1370,7 @@ describe("Parse associations", function () { target_pl: "individuals", target_cp: "Individual", target_cp_pl: "Individuals", - keyIn_lc: "transcript_count", + keysIn_lc: "transcript_count", holdsForeignKey: true, assocThroughArray: false, reverseAssociation: undefined, @@ -1389,7 +1389,7 @@ describe("Parse associations", function () { implementation: "foreignkey", target: "individual", targetKey: "individual_id", - keyIn: "transcript_count", + keysIn: "transcript_count", targetStorageType: "sql", }, ], @@ -1419,7 +1419,7 @@ describe("Parse associations", function () { type: "one_to_many", implementation: "foreignkey", target: "transcript_count", - keyIn: "transcript_count", + keysIn: "transcript_count", targetKey: "individual_id", targetKey_cp: "Individual_id", targetStorageType: "sql", @@ -1431,7 +1431,7 @@ describe("Parse associations", function () { target_pl: "transcript_counts", target_cp: "Transcript_count", target_cp_pl: "Transcript_counts", - keyIn_lc: "transcript_count", + keysIn_lc: "transcript_count", holdsForeignKey: false, assocThroughArray: false, reverseAssociation: undefined, @@ -1448,7 +1448,7 @@ describe("Parse associations", function () { type: "one_to_many", implementation: "foreignkey", target: "transcript_count", - keyIn: "transcript_count", + keysIn: "transcript_count", targetKey: "individual_id", targetStorageType: "sql", }, @@ -1483,6 +1483,7 @@ describe("Parse associations", function () { targetKey_cp: "ProjectId", sourceKey: "researcherId", keysIn: "project_to_researcher", + keysIn_lc: "project_to_researcher", targetStorageType: "sql", source: "researchers", target_lc: "project", @@ -1547,7 +1548,7 @@ describe("Parse associations", function () { target: "Dog", targetKey: "personId", targetKey_cp: "PersonId", - keyIn: "Dog", + keysIn: "Dog", targetStorageType: "sql", name: "dogs", name_lc: "dogs", @@ -1557,7 +1558,7 @@ describe("Parse associations", function () { target_pl: "Dogs", target_cp: "Dog", target_cp_pl: "Dogs", - keyIn_lc: "dog", + keysIn_lc: "dog", holdsForeignKey: false, assocThroughArray: false, reverseAssociation: undefined, @@ -1572,6 +1573,7 @@ describe("Parse associations", function () { targetKey_cp: "BookId", sourceKey: "personId", keysIn: "books_to_people", + keysIn_lc: "books_to_people", targetStorageType: "sql", name: "books", name_lc: "books", @@ -1598,7 +1600,7 @@ describe("Parse associations", function () { implementation: "foreignkey", target: "Dog", targetKey: "personId", - keyIn: "Dog", + keysIn: "Dog", targetStorageType: "sql", }, { @@ -1635,7 +1637,7 @@ describe("Parse associations", function () { target: "Person", targetKey: "personId", targetKey_cp: "PersonId", - keyIn: "Dog", + keysIn: "Dog", targetStorageType: "sql", label: "firstName", sublabel: "lastName", @@ -1647,7 +1649,7 @@ describe("Parse associations", function () { target_pl: "People", target_cp: "Person", target_cp_pl: "People", - keyIn_lc: "dog", + keysIn_lc: "dog", holdsForeignKey: true, assocThroughArray: false, reverseAssociation: undefined, @@ -1658,7 +1660,7 @@ describe("Parse associations", function () { target: "Researcher", targetKey: "researcherId", targetKey_cp: "ResearcherId", - keyIn: "Dog", + keysIn: "Dog", targetStorageType: "sql", label: "firstName", name: "researcher", @@ -1669,7 +1671,7 @@ describe("Parse associations", function () { target_pl: "Researchers", target_cp: "Researcher", target_cp_pl: "Researchers", - keyIn_lc: "dog", + keysIn_lc: "dog", holdsForeignKey: true, assocThroughArray: false, reverseAssociation: undefined, @@ -1689,7 +1691,7 @@ describe("Parse associations", function () { implementation: "foreignkey", target: "Person", targetKey: "personId", - keyIn: "Dog", + keysIn: "Dog", targetStorageType: "sql", label: "firstName", sublabel: "lastName", @@ -1699,7 +1701,7 @@ describe("Parse associations", function () { implementation: "foreignkey", target: "Researcher", targetKey: "researcherId", - keyIn: "Dog", + keysIn: "Dog", targetStorageType: "sql", label: "firstName", }, diff --git a/test/unit_test_misc/data_models.js b/test/unit_test_misc/data_models.js index e879b269..30006a03 100644 --- a/test/unit_test_misc/data_models.js +++ b/test/unit_test_misc/data_models.js @@ -14,7 +14,7 @@ module.exports.transcript_count = { "implementation": "foreignkey", "target" : "individual", "targetKey" : "individual_id", - "keyIn": "transcript_count", + "keysIn": "transcript_count", "targetStorageType" : "sql" } } @@ -31,7 +31,7 @@ module.exports.individual = { "type" : "one_to_many", "implementation": "foreignkey", "target" : "transcript_count", - "keyIn": "transcript_count", + "keysIn": "transcript_count", "targetKey" : "individual_id", "targetStorageType" : "sql" } @@ -71,7 +71,7 @@ module.exports.person = { "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType" : "sql" }, @@ -111,7 +111,7 @@ module.exports.book = { "implementation": "foreignkey", "target" : "Publisher", "targetKey" : "publisherId", - "keyIn": "Book", + "keysIn": "Book", "targetStorageType" : "generic" } } @@ -140,7 +140,7 @@ module.exports.researcher = { "implementation": "foreignkey", "target": "Dog", "targetKey": "researcherId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType": "sql" } } @@ -162,7 +162,7 @@ module.exports.specie = { "implementation": "foreignkey", "target" : "Project", "targetKey" : "specieId", - "keyIn": "Project", + "keysIn": "Project", "targetStorageType" : "sql" } } @@ -182,7 +182,7 @@ module.exports.dog = { "implementation": "foreignkey", "target" : "Person", "targetKey" : "personId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType" : "sql", "label": "firstName", "sublabel": "lastName" @@ -192,7 +192,7 @@ module.exports.dog = { "implementation": "foreignkey", "target": "Researcher", "targetKey": "researcherId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType": "SQL", "label": "firstName" } @@ -220,7 +220,7 @@ module.exports.assoc_dogs_researcher = { "implementation": "foreignkey", "target": "Researcher", "targetKey": "researcherId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType": "SQL", "target_lc": "researcher", "target_lc_pl": "researchers", @@ -253,7 +253,7 @@ module.exports.inDiVIdual_camelcase = { "implementation": "foreignkey", "target" : "transcriptCount", "targetKey" : "individual_id", - "keyIn": "transcriptCount", + "keysIn": "transcriptCount", "targetStorageType" : "sql", "label" : "gene", "sublabel" : "variable" @@ -277,7 +277,7 @@ module.exports.transcriptCount_camelcase = { "implementation": "foreignkey", "target" : "inDiVIdual", "targetKey" : "individual_id", - "keyIn": "transcriptCount", + "keysIn": "transcriptCount", "targetStorageType" : "sql", "label" : "name" } @@ -299,7 +299,7 @@ module.exports.transcriptCount_indiv= { "implementation": "foreignkey", "target" : "Individual", "targetKey" : "individual_id", - "keyIn": "transcriptCount", + "keysIn": "transcriptCount", "targetStorageType" : "sql", "label" : "name" } @@ -322,7 +322,7 @@ module.exports.dog_owner = { "implementation": "foreignkey", "target" : "Person", "targetKey" : "owner_id_test", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType" : "sql", "label": "firstName", "sublabel": "lastName" @@ -332,7 +332,7 @@ module.exports.dog_owner = { "implementation": "foreignkey", "target": "Researcher", "targetKey": "keeperId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType": "SQL", "label": "firstName" } @@ -354,7 +354,7 @@ module.exports.person_indices = { "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType" : "sql", "label": "name" }, @@ -389,7 +389,7 @@ module.exports.person_externalIds = { "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType" : "sql", "label": "name" }, @@ -424,7 +424,7 @@ module.exports.academicTeam = { "implementation": "foreignkey", "target" : "Researcher", "targetKey" : "academicTeamId", - "keyIn": "Researcher", + "keysIn": "Researcher", "targetStorageType" : "sql", "label": "firstName", "sublabel": "lastName" @@ -448,7 +448,7 @@ module.exports.person_date = { "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType" : "sql", "label": "name" }, @@ -458,7 +458,7 @@ module.exports.person_date = { "implementation": "foreignkey", "target" : "Dog", "targetKey" : "doctor_Id", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType" : "sql", "label": "name" }, @@ -503,7 +503,7 @@ module.exports.book_authors = { "implementation": "foreignkey", "target" : "Publisher", "targetKey" : "publisherId", - "keyIn" : "Book", + "keysIn" : "Book", "targetStorageType" : "generic", "label" : "name" } @@ -530,7 +530,7 @@ module.exports.person_description = { "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType" : "sql" }, @@ -565,7 +565,7 @@ module.exports.person_description_optional = { "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType" : "sql" }, @@ -596,7 +596,7 @@ module.exports.academic_Team = { "implementation": "foreignkey", "target" : "Researcher", "targetKey" : "AcademicTeam_Id", - "keyIn": "Researcher", + "keysIn": "Researcher", "targetStorageType" : "sql" } } @@ -618,7 +618,7 @@ module.exports.dog_one_assoc = { "implementation": "foreignkey", "target" : "Person", "targetKey" : "personId", - "keyIn" : "Dog", + "keysIn" : "Dog", "targetStorageType" : "sql" } } @@ -640,7 +640,7 @@ module.exports.person_one_assoc = { "implementation": "foreignkey", "target": "Dog", "targetKey": "personId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType": "sql" } } @@ -662,7 +662,7 @@ module.exports.book_extendedIds = { "implementation": "foreignkey", "target": "Person", "targetKey": "internalPersonId", - "keyIn": "Book", + "keysIn": "Book", "targetStorageType": "sql", "label": "email" } @@ -689,7 +689,7 @@ module.exports.author_foreignKeyArray = { "target": "book", "targetKey": "author_ids", "sourceKey": "book_ids", - "keyIn": "author", + "keysIn": "author", "targetStorageType": "sql" } }, @@ -716,7 +716,7 @@ module.exports.author_zendro_remote = { "target": "post_book", "targetKey": "author_ids", "sourceKey": "book_ids", - "keyIn": "post_author", + "keysIn": "post_author", "targetStorageType": "zendro-server" } }, @@ -742,7 +742,7 @@ module.exports.author_ddm_array_fk ={ "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", - "keyIn": "sq_author", + "keysIn": "sq_author", "targetStorageType": "distributed-data-model" } }, @@ -769,7 +769,7 @@ module.exports.author_sql_adapter_array_fk ={ "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", - "keyIn": "sq_author", + "keysIn": "sq_author", "targetStorageType": "distributed-data-model" } }, @@ -798,7 +798,7 @@ module.exports.author_zendro_adapter_array_fk ={ "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", - "keyIn": "sq_author", + "keysIn": "sq_author", "targetStorageType": "distributed-data-model" } }, diff --git a/test/unit_test_misc/data_models_cassandra.js b/test/unit_test_misc/data_models_cassandra.js index 134069ba..019a5fb0 100644 --- a/test/unit_test_misc/data_models_cassandra.js +++ b/test/unit_test_misc/data_models_cassandra.js @@ -21,7 +21,7 @@ module.exports.city = { "targetStorageType": "sql", "sourceKey": "river_ids", "targetKey": "city_ids", - "keyIn": "city", + "keysIn": "city", } }, "internalId": "city_id" @@ -44,7 +44,7 @@ module.exports.incident = { "implementation": "foreignkey", "target": "Instant", "targetKey": "incident_assoc_id", - "keyIn" : "Instant", + "keysIn" : "Instant", "targetStorageType": "cassandra" }, "town": { @@ -52,7 +52,7 @@ module.exports.incident = { "implementation": "foreignkey", "target": "capital", "targetKey": "capital_id", - "keyIn" : "Incident", + "keysIn" : "Incident", "targetStorageType": "sql" } @@ -79,7 +79,7 @@ module.exports.dist_incident = { "implementation": "foreignkey", "target": "Dist_instant", "targetKey": "incident_assoc_id", - "keyIn" : "Dist_instant", + "keysIn" : "Dist_instant", "targetStorageType": "distributed-data-model" } @@ -106,7 +106,7 @@ module.exports.dist_instant_instance1 = { "implementation": "foreignkey", "target": "Dist_instant", "targetKey": "incident_assoc_id", - "keyIn": "Dist_instant", + "keysIn": "Dist_instant", "targetStorageType": "distributed-data-model" } diff --git a/test/unit_test_misc/data_models_distributed.js b/test/unit_test_misc/data_models_distributed.js index 8f036f7b..b2008902 100644 --- a/test/unit_test_misc/data_models_distributed.js +++ b/test/unit_test_misc/data_models_distributed.js @@ -27,7 +27,7 @@ module.exports.book = { "implementation": "foreignkey", "target" : "publi_sher", "targetKey" : "publisher_id", - "keyIn" : "Book", + "keysIn" : "Book", "targetStorageType" : "zendro-server", "label" : "name" } @@ -63,7 +63,7 @@ module.exports.book_ddm = "implementation": "foreignkey", "target" : "publi_sher", "targetKey" : "publisher_id", - "keyIn" : "Book", + "keysIn" : "Book", "targetStorageType" : "zendro-server", "label" : "name" } @@ -98,7 +98,7 @@ module.exports.person_ddm = { "implementation": "foreignkey", "target": "publi_sher", "targetKey": "companyId", - "keyIn": "Person", + "keysIn": "Person", "targetStorageType": "zendro-server" }, @@ -107,7 +107,7 @@ module.exports.person_ddm = { "implementation": "foreignkey", "target": "Dog", "targetKey": "personId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType": "sql" }, @@ -116,7 +116,7 @@ module.exports.person_ddm = { "implementation": "foreignkey", "target": "Parrot", "targetKey": "personId", - "keyIn": "Parrot", + "keysIn": "Parrot", "targetStorageType": "sql" }, } @@ -140,7 +140,7 @@ module.exports.dog_ddm = { "implementation": "foreignkey", "target" : "Person", "targetKey" : "personId", - "keyIn" : "Dog", + "keysIn" : "Dog", "targetStorageType" : "sql" } } @@ -166,7 +166,7 @@ module.exports.dog_ddm = { "implementation": "foreignkey", "target": "Book", "targetKey": "internalPersonId", - "keyIn": "Book", + "keysIn": "Book", "targetStorageType": "sql", "label": "title" } @@ -213,7 +213,7 @@ module.exports.dog_ddm = { "implementation": "foreignkey", "target": "Person", "targetKey": "internalPersonId", - "keyIn": "Book", + "keysIn": "Book", "targetStorageType": "zendro-server", "label": "email" } @@ -236,7 +236,7 @@ module.exports.dog_ddm_integration_test = { "implementation": "foreignkey", "target" : "person", "targetKey" : "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType" : "distributed-data-model" } }, @@ -262,7 +262,7 @@ module.exports.dog_zendro_adapter_integration_test = "implementation": "foreignkey", "target" : "person", "targetKey" : "person_id", - "keyIn": "dog", + "keysIn": "dog", "targetStorageType" : "distributed-data-model" } }, diff --git a/test/unit_test_misc/data_models_extendedId.js b/test/unit_test_misc/data_models_extendedId.js index eb1f6c48..497182e4 100644 --- a/test/unit_test_misc/data_models_extendedId.js +++ b/test/unit_test_misc/data_models_extendedId.js @@ -16,7 +16,7 @@ module.exports.book_adapter = { "implementation": "foreignkey", "target": "Person", "targetKey": "internalPersonId", - "keyIn": "Book", + "keysIn": "Book", "targetStorageType": "sql", "label": "email" } @@ -43,7 +43,7 @@ module.exports.book_ddm = { "implementation": "foreignkey", "target": "Person", "targetKey": "internalPersonId", - "keyIn": "Book", + "keysIn": "Book", "targetStorageType": "zendro-server", "label": "email" } @@ -70,7 +70,7 @@ module.exports.person_adapter = { "implementation": "foreignkey", "target": "Book", "targetKey": "internalPersonId", - "keyIn": "Book", + "keysIn": "Book", "targetStorageType": "sql", "label": "title" } @@ -98,7 +98,7 @@ module.exports.person_ddm = { "implementation": "foreignkey", "target": "Book", "targetKey": "internalPersonId", - "keyIn": "Book", + "keysIn": "Book", "targetStorageType": "zendro-server", "label": "title" } diff --git a/test/unit_test_misc/data_models_generic.js b/test/unit_test_misc/data_models_generic.js index b120fda8..7ce205aa 100644 --- a/test/unit_test_misc/data_models_generic.js +++ b/test/unit_test_misc/data_models_generic.js @@ -26,7 +26,7 @@ module.exports.personSql_toMany_dogGeneric = { "implementation": "foreignkey", "target" : "Dog", "targetKey" : "personId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType" : "generic", "label": "name" } @@ -47,7 +47,7 @@ module.exports.dogGeneric_toOne_personSql = { "implementation": "foreignkey", "target" : "Person", "targetKey" : "personId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType" : "sql", "label": "firstName", "sublabel": "lastName" @@ -72,7 +72,7 @@ module.exports.personSql_toOne_hometownGeneric = { "implementation": "foreignkey", "target" : "Hometown", "targetKey" : "hometownId", - "keyIn": "Person", + "keysIn": "Person", "targetStorageType" : "generic", "label": "name" } @@ -95,7 +95,7 @@ module.exports.hometownGeneric_toMany_personSql = { "implementation": "foreignkey", "target" : "Person", "targetKey" : "hometownId", - "keyIn": "Person", + "keysIn": "Person", "targetStorageType" : "sql", "label": "firstName", "sublabel": "lastName" diff --git a/test/unit_test_misc/data_models_generic_webservice.js b/test/unit_test_misc/data_models_generic_webservice.js index 63f861e4..59ec5ab0 100644 --- a/test/unit_test_misc/data_models_generic_webservice.js +++ b/test/unit_test_misc/data_models_generic_webservice.js @@ -14,7 +14,7 @@ module.exports.book = "implementation": "foreignkey", "target": "publi_sher", "targetKey": "publisher_id", - "keyIn": "book", + "keysIn": "book", "targetStorageType": "generic" }, @@ -55,7 +55,7 @@ module.exports.person = "implementation": "foreignkey", "target": "publi_sher", "targetKey": "companyId", - "keyIn": "Person", + "keysIn": "Person", "targetStorageType": "generic" } } @@ -77,7 +77,7 @@ module.exports.publisher = "implementation": "foreignkey", "target": "book", "targetKey": "publisher_id", - "keyIn": "book", + "keysIn": "book", "targetStorageType": "generic" }, @@ -86,7 +86,7 @@ module.exports.publisher = "implementation": "foreignkey", "target": "Person", "targetKey": "companyId", - "keyIn": "Person", + "keysIn": "Person", "targetStorageType": "generic" } } diff --git a/test/unit_test_misc/data_models_mongodb.js b/test/unit_test_misc/data_models_mongodb.js index caae1074..f8664955 100644 --- a/test/unit_test_misc/data_models_mongodb.js +++ b/test/unit_test_misc/data_models_mongodb.js @@ -19,7 +19,7 @@ module.exports.animal = { implementation: "foreignkey", target: "farm", targetKey: "farm_id", - keyIn: "animal", + keysIn: "animal", targetStorageType: "mongodb", label: "farm_name", }, @@ -29,7 +29,7 @@ module.exports.animal = { target: "food", targetKey: "animal_ids", sourceKey: "food_ids", - keyIn: "animal", + keysIn: "animal", targetStorageType: "mongodb", }, }, @@ -63,7 +63,7 @@ module.exports.dist_animal_instance1 = { implementation: "foreignkey", target: "dist_farm", targetKey: "farm_id", - keyIn: "dist_animal", + keysIn: "dist_animal", targetStorageType: "distributed-data-model", }, }, diff --git a/test/unit_test_misc/data_models_refactoring.js b/test/unit_test_misc/data_models_refactoring.js index 9b9500f2..342e8c2b 100644 --- a/test/unit_test_misc/data_models_refactoring.js +++ b/test/unit_test_misc/data_models_refactoring.js @@ -16,7 +16,7 @@ module.exports.accession = { "implementation": "foreignkey", "target": "Individual", "targetKey": "accessionId", - "keyIn" : "Individual", + "keysIn" : "Individual", "targetStorageType": "sql", "label": "name" }, @@ -26,7 +26,7 @@ module.exports.accession = { "implementation": "foreignkey", "target": "Location", "targetKey": "locationId", - "keyIn" : "Accession", + "keysIn" : "Accession", "targetStorageType": "sql", "label": "country", "sublabel": "state" @@ -37,7 +37,7 @@ module.exports.accession = { "implementation": "foreignkey", "target": "Measurement", "targetKey": "accessionId", - "keyIn" : "Measurement", + "keysIn" : "Measurement", "targetStorageType": "sql", "label": "name" } @@ -66,7 +66,7 @@ module.exports.accession_ddm = { "implementation": "foreignkey", "target": "Individual", "targetKey": "accessionId", - "keyIn" : "Individual", + "keysIn" : "Individual", "targetStorageType": "distributed-data-model", "label": "name" }, @@ -76,7 +76,7 @@ module.exports.accession_ddm = { "implementation": "foreignkey", "target": "Location", "targetKey": "locationId", - "keyIn" : "Accession", + "keysIn" : "Accession", "targetStorageType": "sql", "label": "country", "sublabel": "state" @@ -87,7 +87,7 @@ module.exports.accession_ddm = { "implementation": "foreignkey", "target": "Measurement", "targetKey": "accessionId", - "keyIn" : "Measurement", + "keysIn" : "Measurement", "targetStorageType": "sql", "label": "name" } @@ -117,7 +117,7 @@ module.exports.accession_sql_adapter = { "implementation": "foreignkey", "target": "Individual", "targetKey": "accessionId", - "keyIn" : "Individual", + "keysIn" : "Individual", "targetStorageType": "sql", "label": "name" }, @@ -127,7 +127,7 @@ module.exports.accession_sql_adapter = { "implementation": "foreignkey", "target": "Location", "targetKey": "locationId", - "keyIn" : "Accession", + "keysIn" : "Accession", "targetStorageType": "sql", "label": "country", "sublabel": "state" @@ -138,7 +138,7 @@ module.exports.accession_sql_adapter = { "implementation": "foreignkey", "target": "Measurement", "targetKey": "accession_id", - "keyIn" : "Measurement", + "keysIn" : "Measurement", "targetStorageType": "sql", "label": "name" } @@ -168,7 +168,7 @@ module.exports.accession_zendro_adapter = { "implementation": "foreignkey", "target": "Individual", "targetKey": "accessionId", - "keyIn" : "Individual", + "keysIn" : "Individual", "targetStorageType": "sql", "label": "name" }, @@ -179,7 +179,7 @@ module.exports.accession_zendro_adapter = { "implementation": "foreignkey", "target": "Location", "targetKey": "locationId", - "keyIn" : "Accession", + "keysIn" : "Accession", "targetStorageType": "sql", "label": "country", "sublabel": "state" @@ -190,7 +190,7 @@ module.exports.accession_zendro_adapter = { "implementation": "foreignkey", "target": "Measurement", "targetKey": "accession_id", - "keyIn" : "Measurement", + "keysIn" : "Measurement", "targetStorageType": "sql", "label": "name" } diff --git a/test/unit_test_misc/data_models_zendro.js b/test/unit_test_misc/data_models_zendro.js index 01a0f8db..ccdd0832 100644 --- a/test/unit_test_misc/data_models_zendro.js +++ b/test/unit_test_misc/data_models_zendro.js @@ -25,7 +25,7 @@ module.exports.book = { "implementation": "foreignkey", "target" : "publi_sher", "targetKey" : "publisher_id", - "keyIn" : "Book", + "keysIn" : "Book", "targetStorageType" : "generic", "label" : "name" } @@ -59,7 +59,7 @@ module.exports.person = { "implementation": "foreignkey", "target": "publi_sher", "targetKey": "companyId", - "keyIn": "Person", + "keysIn": "Person", "targetStorageType": "generic" } } @@ -82,7 +82,7 @@ module.exports.dog_one_assoc = { "implementation": "foreignkey", "target" : "Person", "targetKey" : "personId", - "keyIn" : "Dog", + "keysIn" : "Dog", "targetStorageType" : "sql" }, @@ -91,7 +91,7 @@ module.exports.dog_one_assoc = { "implementation": "foreignkey", "target" : "Person", "targetKey" : "veterinarianId", - "keyIn" : "Dog", + "keysIn" : "Dog", "targetStorageType" : "sql" } } @@ -114,7 +114,7 @@ module.exports.person_one_assoc = { "implementation": "foreignkey", "target": "Dog", "targetKey": "personId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType": "sql" }, @@ -123,7 +123,7 @@ module.exports.person_one_assoc = { "implementation": "foreignkey", "target": "Dog", "targetKey": "veterinarianId", - "keyIn": "Dog", + "keysIn": "Dog", "targetStorageType": "sql" } } diff --git a/test/unit_test_misc/test-describe/distributed-models.js b/test/unit_test_misc/test-describe/distributed-models.js index a0fce6cb..0fa81eb9 100644 --- a/test/unit_test_misc/test-describe/distributed-models.js +++ b/test/unit_test_misc/test-describe/distributed-models.js @@ -341,7 +341,7 @@ const definition = { implementation: 'foreignkey', target: 'publi_sher', targetKey: 'companyId', - keyIn: 'Person', + keysIn: 'Person', targetStorageType: 'zendro-server' }, dogs: { @@ -349,7 +349,7 @@ const definition = { implementation: 'foreignkey', target: 'Dog', targetKey: 'personId', - keyIn: 'Dog', + keysIn: 'Dog', targetStorageType: 'sql' }, parrot: { @@ -357,7 +357,7 @@ const definition = { implementation: 'foreignkey', target: 'Parrot', targetKey: 'personId', - keyIn: 'Parrot', + keysIn: 'Parrot', targetStorageType: 'sql' } }, @@ -386,7 +386,7 @@ const definition = { implementation: 'foreignkey', target: 'Person', targetKey: 'personId', - keyIn: 'Dog', + keysIn: 'Dog', targetStorageType: 'sql' } }, diff --git a/test/unit_test_misc/test-describe/zendro-servers.js b/test/unit_test_misc/test-describe/zendro-servers.js index 42b3e4c1..59f69271 100644 --- a/test/unit_test_misc/test-describe/zendro-servers.js +++ b/test/unit_test_misc/test-describe/zendro-servers.js @@ -273,7 +273,7 @@ const definition = { implementation: 'foreignkey', target: 'publi_sher', targetKey: 'companyId', - keyIn: 'Person', + keysIn: 'Person', targetStorageType: 'generic' } }, diff --git a/views/create-models.ejs b/views/create-models.ejs index a1034eb5..e6ef0c11 100644 --- a/views/create-models.ejs +++ b/views/create-models.ejs @@ -113,13 +113,13 @@ module.exports = class <%- nameLc -%> extends Sequelize.Model{ <%for(let i=0; i< associationsArguments[key].length; i++){-%> <%if (key !== 'associations'){-%> <%if(associationsArguments[key][i].targetStorageType === 'sql' && !associationsArguments[key][i].assocThroughArray){-%> - <%if (associationsArguments[key][i].type.includes('to_one') && associationsArguments[key][i].keyIn !== associationsArguments[key][i].target){-%> + <%if (associationsArguments[key][i].type.includes('to_one') && associationsArguments[key][i].keysIn !== associationsArguments[key][i].target){-%> <%- nameLc -%>.belongsTo(models.<%= associationsArguments[key][i].target_lc -%> <%}-%> - <% if (associationsArguments[key][i].type.includes('to_one') && associationsArguments[key][i].keyIn === associationsArguments[key][i].target){-%> + <% if (associationsArguments[key][i].type.includes('to_one') && associationsArguments[key][i].keysIn === associationsArguments[key][i].target){-%> <%- nameLc -%>.hasOne(models.<%= associationsArguments[key][i].target_lc -%> <%}-%> - <% if (associationsArguments[key][i].type === 'one_to_many' && associationsArguments[key][i].keyIn === associationsArguments[key][i].target){-%> + <% if (associationsArguments[key][i].type === 'one_to_many' && associationsArguments[key][i].keysIn === associationsArguments[key][i].target){-%> <%- nameLc -%>.hasMany(models.<%= associationsArguments[key][i].target_lc -%> <%}-%> <% if (associationsArguments[key][i].type === 'many_to_many' && associationsArguments[key][i].implementation === 'sql_cross_table'){-%> From 87a14ff5340eea4150904ebd222dfb60b7d9f161 Mon Sep 17 00:00:00 2001 From: coeit Date: Thu, 10 Jun 2021 17:23:35 +0200 Subject: [PATCH 10/18] refactor: update README for keysIn --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5450414a..8b7f2c5d 100644 --- a/README.md +++ b/README.md @@ -177,12 +177,15 @@ name | Type | Description *label* | String | Name of the column in the target model to be used as a display name in the GUI. *sublabel* | String | Optional name of the column in the target model to be used as a sub-label in the GUI. -When the association is of type *many_to_many* it's necessary to describe two extra arguments given that the association is made with a cross table. These arguments are: +**Note**: The `keysIn` argument points to the model that stores the information about the foreignKey(s). That can be either a single key, a foreignkey array or a cross-model. + +When the association is of type *many_to_many* it's necessary to describe an extra argument *sourceKey*: name | Type | Description ------- | ------- | -------------- *sourceKey* | String | Key to identify the source id -*keysIn* | String | Name of the cross table + +Be aware that in case of a *many_to_many* via an *sql_cross_table* implementation the keysIn field points to the cross model. ## NOTE: Be aware that in the case of this type of association the user is required to describe the cross table used in the field _keysIn_ as a model in its own. For example, if we have a model `User` and a model `Role` and they are associated in a `many_to_many` way, then we also need to describe the `role_to_user` model: From f1887c7e47922a3cb175fc94a0092cbb04fd0612 Mon Sep 17 00:00:00 2001 From: coeit Date: Mon, 14 Jun 2021 10:07:31 +0200 Subject: [PATCH 11/18] refactor: rename assoc field "foreignkey" -> "foreignkeys" --- README.md | 12 ++-- funks.js | 4 +- .../accession.json | 4 +- .../amino_acid_sequence.json | 2 +- .../animal.json | 6 +- .../author.json | 2 +- .../book.json | 2 +- .../capital.json | 4 +- .../cassandra-city.json | 2 +- .../cassandra-incident.json | 4 +- .../cassandra-instant.json | 2 +- .../country.json | 2 +- .../dist_animal.json | 2 +- .../dist_animal_instance1.json | 2 +- .../dist_farm.json | 2 +- .../dist_farm_instance1.json | 2 +- .../dist_incident.json | 2 +- .../dist_incident_instance1.json | 2 +- .../dist_instant.json | 2 +- .../dist_instant_instance1.json | 2 +- .../dog.json | 2 +- .../dog_instance1_adapter.json | 2 +- .../dog_instance2_adapter.json | 2 +- .../farm.json | 2 +- .../food.json | 2 +- .../individual.json | 2 +- .../location.json | 2 +- .../measurement.json | 2 +- .../parrot.json | 2 +- .../parrot_instance1_adapter.json | 2 +- .../parrot_instance2_adapter.json | 2 +- .../person.json | 4 +- .../person_instance1_adapter.json | 4 +- .../person_instance2_adapter.json | 4 +- .../river.json | 2 +- .../sq_author.json | 2 +- .../sq_book.json | 2 +- .../tracker.json | 2 +- .../transcript_count.json | 4 +- .../accession.json | 4 +- .../author.json | 2 +- .../book.json | 2 +- .../dog.json | 2 +- .../dog_instance1_adapter.json | 2 +- .../dog_instance2_adapter.json | 2 +- .../location.json | 2 +- .../measurement.json | 2 +- .../parrot.json | 2 +- .../parrot_instance1_adapter.json | 2 +- .../parrot_instance2_adapter.json | 2 +- .../person.json | 4 +- .../person_instance1_adapter.json | 4 +- .../person_instance2_adapter.json | 4 +- .../sq_author_adapter.json | 2 +- .../sq_author_ddm.json | 2 +- .../sq_author_zendro_adapter.json | 2 +- .../sq_book_adapter.json | 2 +- .../sq_book_ddm.json | 2 +- .../sq_book_zendro_adapter.json | 2 +- test/mocha_unit.test.js | 20 +++--- test/unit_test_misc/data_models.js | 62 +++++++++---------- test/unit_test_misc/data_models_cassandra.js | 10 +-- .../unit_test_misc/data_models_distributed.js | 20 +++--- test/unit_test_misc/data_models_extendedId.js | 8 +-- test/unit_test_misc/data_models_generic.js | 8 +-- .../data_models_generic_webservice.js | 12 ++-- test/unit_test_misc/data_models_mongodb.js | 6 +- .../unit_test_misc/data_models_refactoring.js | 24 +++---- test/unit_test_misc/data_models_zendro.js | 12 ++-- .../test-describe/distributed-models.js | 8 +-- .../test-describe/zendro-servers.js | 2 +- 71 files changed, 174 insertions(+), 174 deletions(-) diff --git a/README.md b/README.md index 8b7f2c5d..1b121bf4 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ EXAMPLES OF VALID JSON FILES "associations" : { "person" : { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "reverseAssociation": "dogs", "target" : "Person", "targetKey" : "personId", @@ -122,7 +122,7 @@ EXAMPLES OF VALID JSON FILES "associations":{ "books" : { "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "reverseAssociation": "publisher", "target" : "Book", "targetKey" : "publisherId", @@ -163,12 +163,12 @@ We will consider four types of associations according to the relation between as 3. one_to_many 4. many_to_many -For both type of association, the necessary arguments would be: +For all types of association, the necessary arguments would be: name | Type | Description ------- | ------- | -------------- *type* | String | Type of association (`one_to_one`, `one_to_many`, etc.) -*implementation* | String | implementation type of the association. Can be one of `foreignkey`, `generic` or `sql_cross_table` (only for `many_to_many`)` +*implementation* | String | implementation type of the association. Can be one of `foreignkeys`, `generic` or `sql_cross_table` (only for `many_to_many`)` *reverseAssociation* | String | The name of the reverse association from the other model. This field is only mandatory for building the [single-page-app](https://github.com/Zendro-dev/single-page-app), *not* for generating the the graphql-server code via this repository. *target* | String | Name of model to which the current model will be associated with. *targetKey* | String | A unique identifier of the association for the case where there appear more than one association with the same model. @@ -202,7 +202,7 @@ Be aware that in the case of this type of association the user is required to de "associations" :{ "roles" : { "type" : "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "reverseAssociation": "dogs", "target" : "Role", "targetKey" : "role_Id", @@ -269,7 +269,7 @@ Example: "associations":{ "publisher" : { "type" : "to_one", // association type - "implementation": "foreignkey", // standard implementation via foreign keys + "implementation": "foreignkeys", // standard implementation via foreign keys "reverseAssociation": "dogs", // name of the association in the publisher model "target" : "publisher", // Model's name is `publisher` "targetKey" : "publisher_id", // Local alias for this association diff --git a/funks.js b/funks.js index 68ee494b..1f966cc3 100644 --- a/funks.js +++ b/funks.js @@ -713,7 +713,7 @@ getEditableAttributes = function ( ) { let editable_attributes = {}; let target_keys = parsedAssocForeignKeys.map((assoc) => { - if (assoc.type === 'many_to_many' && assoc.implementation === 'foreignkey') return assoc.sourceKey; + if (assoc.type === 'many_to_many' && assoc.implementation === 'foreignkeys') return assoc.sourceKey; return assoc.targetKey; }); for (let attrib in attributes) { @@ -833,7 +833,7 @@ module.exports.parseAssociations = function (dataModel) { associations_info.schema_attributes["many"][name] = schema_attributes; associations_info['to_many_through_sql_cross_table'].push(assoc); break; - case 'foreignkey': + case 'foreignkeys': associations_info.foreignKeyAssociations[name] = association.targetKey; switch (type) { case 'one_to_one': diff --git a/test/integration_test_misc/integration_test_models_instance1/accession.json b/test/integration_test_misc/integration_test_models_instance1/accession.json index fcafd2f4..58d960a4 100644 --- a/test/integration_test_misc/integration_test_models_instance1/accession.json +++ b/test/integration_test_misc/integration_test_models_instance1/accession.json @@ -13,7 +13,7 @@ "location": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Location", "targetKey": "locationId", "keysIn": "Accession", @@ -24,7 +24,7 @@ "measurements": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Measurement", "targetKey": "accessionId", "keysIn": "Measurement", diff --git a/test/integration_test_misc/integration_test_models_instance1/amino_acid_sequence.json b/test/integration_test_misc/integration_test_models_instance1/amino_acid_sequence.json index 71dcd7ac..3e3dcae5 100644 --- a/test/integration_test_misc/integration_test_models_instance1/amino_acid_sequence.json +++ b/test/integration_test_misc/integration_test_models_instance1/amino_acid_sequence.json @@ -8,7 +8,7 @@ "associations": { "transcript_counts": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "transcript_count", "targetKey": "aminoacidsequence_id", "keysIn": "transcript_count", diff --git a/test/integration_test_misc/integration_test_models_instance1/animal.json b/test/integration_test_misc/integration_test_models_instance1/animal.json index c7de2820..8faadb4e 100644 --- a/test/integration_test_misc/integration_test_models_instance1/animal.json +++ b/test/integration_test_misc/integration_test_models_instance1/animal.json @@ -16,7 +16,7 @@ "associations": { "farm": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "farm", "targetKey": "farm_id", "keysIn": "animal", @@ -25,7 +25,7 @@ }, "food": { "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "food", "targetKey": "animal_ids", "sourceKey": "food_ids", @@ -34,7 +34,7 @@ }, "unique_tracker": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "tracker", "targetKey": "animal_id", "keysIn": "tracker", diff --git a/test/integration_test_misc/integration_test_models_instance1/author.json b/test/integration_test_misc/integration_test_models_instance1/author.json index 6d58dec6..742ea191 100644 --- a/test/integration_test_misc/integration_test_models_instance1/author.json +++ b/test/integration_test_misc/integration_test_models_instance1/author.json @@ -13,7 +13,7 @@ "associations": { "books": { "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance1/book.json b/test/integration_test_misc/integration_test_models_instance1/book.json index 0f902024..f0c6b2c6 100644 --- a/test/integration_test_misc/integration_test_models_instance1/book.json +++ b/test/integration_test_misc/integration_test_models_instance1/book.json @@ -13,7 +13,7 @@ "associations": { "authors": { "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/integration_test_misc/integration_test_models_instance1/capital.json b/test/integration_test_misc/integration_test_models_instance1/capital.json index 07f1797e..40bea893 100644 --- a/test/integration_test_misc/integration_test_models_instance1/capital.json +++ b/test/integration_test_misc/integration_test_models_instance1/capital.json @@ -9,7 +9,7 @@ "associations": { "unique_country": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "country", "targetKey": "country_id", "keysIn": "capital", @@ -17,7 +17,7 @@ }, "incidents": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Incident", "targetKey": "capital_id", "keysIn": "Incident", diff --git a/test/integration_test_misc/integration_test_models_instance1/cassandra-city.json b/test/integration_test_misc/integration_test_models_instance1/cassandra-city.json index 5e7876c0..3fb78bab 100644 --- a/test/integration_test_misc/integration_test_models_instance1/cassandra-city.json +++ b/test/integration_test_misc/integration_test_models_instance1/cassandra-city.json @@ -16,7 +16,7 @@ "associations": { "rivers": { "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "river", "targetStorageType": "sql", "sourceKey": "river_ids", diff --git a/test/integration_test_misc/integration_test_models_instance1/cassandra-incident.json b/test/integration_test_misc/integration_test_models_instance1/cassandra-incident.json index 63ac885b..da50eb16 100644 --- a/test/integration_test_misc/integration_test_models_instance1/cassandra-incident.json +++ b/test/integration_test_misc/integration_test_models_instance1/cassandra-incident.json @@ -12,7 +12,7 @@ "instants": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Instant", "targetKey": "incident_assoc_id", "keysIn": "Instant", @@ -20,7 +20,7 @@ }, "town": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "capital", "targetKey": "capital_id", "keysIn": "Incident", diff --git a/test/integration_test_misc/integration_test_models_instance1/cassandra-instant.json b/test/integration_test_misc/integration_test_models_instance1/cassandra-instant.json index 358fe7a7..0a320877 100644 --- a/test/integration_test_misc/integration_test_models_instance1/cassandra-instant.json +++ b/test/integration_test_misc/integration_test_models_instance1/cassandra-instant.json @@ -15,7 +15,7 @@ "incident": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Incident", "targetKey": "incident_assoc_id", "keysIn": "Instant", diff --git a/test/integration_test_misc/integration_test_models_instance1/country.json b/test/integration_test_misc/integration_test_models_instance1/country.json index de25463e..b130c544 100644 --- a/test/integration_test_misc/integration_test_models_instance1/country.json +++ b/test/integration_test_misc/integration_test_models_instance1/country.json @@ -8,7 +8,7 @@ "associations": { "unique_capital": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "capital", "targetKey": "country_id", "keysIn": "capital", diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_animal.json b/test/integration_test_misc/integration_test_models_instance1/dist_animal.json index 6197981d..0bb74557 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_animal.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_animal.json @@ -17,7 +17,7 @@ "associations": { "dist_farm": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "dist_farm", "targetKey": "farm_id", "keysIn": "dist_animal", diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_animal_instance1.json b/test/integration_test_misc/integration_test_models_instance1/dist_animal_instance1.json index 18f5cffc..e91566b1 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_animal_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_animal_instance1.json @@ -19,7 +19,7 @@ "dist_farm": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "dist_farm", "targetKey": "farm_id", "keysIn": "dist_animal", diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_farm.json b/test/integration_test_misc/integration_test_models_instance1/dist_farm.json index 2ed825a5..3bd964b6 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_farm.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_farm.json @@ -10,7 +10,7 @@ "associations": { "dist_animals": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "dist_animal", "targetKey": "farm_id", "keysIn": "dist_animal", diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_farm_instance1.json b/test/integration_test_misc/integration_test_models_instance1/dist_farm_instance1.json index 93d6a8ba..2c8e9b0f 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_farm_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_farm_instance1.json @@ -11,7 +11,7 @@ "associations": { "dist_animals": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "dist_animal", "targetKey": "farm_id", "keysIn": "dist_animal", diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_incident.json b/test/integration_test_misc/integration_test_models_instance1/dist_incident.json index d1339603..3b00b37c 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_incident.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_incident.json @@ -13,7 +13,7 @@ "dist_instants": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Dist_instant", "targetKey": "incident_assoc_id", "keysIn": "Dist_instant", diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_incident_instance1.json b/test/integration_test_misc/integration_test_models_instance1/dist_incident_instance1.json index 2423430d..0e7fcc97 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_incident_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_incident_instance1.json @@ -13,7 +13,7 @@ "dist_instants": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Dist_instant", "targetKey": "incident_assoc_id", "keysIn": "Dist_instant", diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_instant.json b/test/integration_test_misc/integration_test_models_instance1/dist_instant.json index be113bec..dbee7c62 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_instant.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_instant.json @@ -17,7 +17,7 @@ "dist_incident": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Dist_incident", "targetKey": "incident_assoc_id", "keysIn": "Dist_instant", diff --git a/test/integration_test_misc/integration_test_models_instance1/dist_instant_instance1.json b/test/integration_test_misc/integration_test_models_instance1/dist_instant_instance1.json index 37670d6d..fe458359 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dist_instant_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance1/dist_instant_instance1.json @@ -17,7 +17,7 @@ "dist_incident": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Dist_incident", "targetKey": "incident_assoc_id", "keysIn": "Dist_instant", diff --git a/test/integration_test_misc/integration_test_models_instance1/dog.json b/test/integration_test_misc/integration_test_models_instance1/dog.json index 1c5211d7..00627f6a 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dog.json +++ b/test/integration_test_misc/integration_test_models_instance1/dog.json @@ -10,7 +10,7 @@ "associations": { "person": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "person", "targetKey": "person_id", "keysIn": "dog", diff --git a/test/integration_test_misc/integration_test_models_instance1/dog_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance1/dog_instance1_adapter.json index 59bf7c4a..462272a4 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dog_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/dog_instance1_adapter.json @@ -11,7 +11,7 @@ "associations": { "person": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "person", "targetKey": "person_id", "keysIn": "dog", diff --git a/test/integration_test_misc/integration_test_models_instance1/dog_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance1/dog_instance2_adapter.json index 650e1e5e..c3a903a1 100644 --- a/test/integration_test_misc/integration_test_models_instance1/dog_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/dog_instance2_adapter.json @@ -12,7 +12,7 @@ "associations": { "person": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "person", "targetKey": "person_id", "keysIn": "dog", diff --git a/test/integration_test_misc/integration_test_models_instance1/farm.json b/test/integration_test_misc/integration_test_models_instance1/farm.json index 1874a691..c303f166 100644 --- a/test/integration_test_misc/integration_test_models_instance1/farm.json +++ b/test/integration_test_misc/integration_test_models_instance1/farm.json @@ -9,7 +9,7 @@ "associations": { "animals": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "animal", "targetKey": "farm_id", "keysIn": "animal", diff --git a/test/integration_test_misc/integration_test_models_instance1/food.json b/test/integration_test_misc/integration_test_models_instance1/food.json index 02ed169b..005a14e5 100644 --- a/test/integration_test_misc/integration_test_models_instance1/food.json +++ b/test/integration_test_misc/integration_test_models_instance1/food.json @@ -10,7 +10,7 @@ "associations": { "animals": { "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "animal", "targetKey": "food_ids", "sourceKey": "animal_ids", diff --git a/test/integration_test_misc/integration_test_models_instance1/individual.json b/test/integration_test_misc/integration_test_models_instance1/individual.json index 5fb42a13..2a513bf0 100644 --- a/test/integration_test_misc/integration_test_models_instance1/individual.json +++ b/test/integration_test_misc/integration_test_models_instance1/individual.json @@ -7,7 +7,7 @@ "associations": { "transcript_counts": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "transcript_count", "targetKey": "individual_id", "keysIn": "transcript_count", diff --git a/test/integration_test_misc/integration_test_models_instance1/location.json b/test/integration_test_misc/integration_test_models_instance1/location.json index 28b4258c..9acfaeaa 100644 --- a/test/integration_test_misc/integration_test_models_instance1/location.json +++ b/test/integration_test_misc/integration_test_models_instance1/location.json @@ -13,7 +13,7 @@ "accessions": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Accession", "targetKey": "locationId", "keysIn": "Accession", diff --git a/test/integration_test_misc/integration_test_models_instance1/measurement.json b/test/integration_test_misc/integration_test_models_instance1/measurement.json index 9aa42b00..681ee940 100644 --- a/test/integration_test_misc/integration_test_models_instance1/measurement.json +++ b/test/integration_test_misc/integration_test_models_instance1/measurement.json @@ -12,7 +12,7 @@ "accession": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Accession", "targetKey": "accessionId", "keysIn": "Measurement", diff --git a/test/integration_test_misc/integration_test_models_instance1/parrot.json b/test/integration_test_misc/integration_test_models_instance1/parrot.json index 9921ef6a..eb753066 100644 --- a/test/integration_test_misc/integration_test_models_instance1/parrot.json +++ b/test/integration_test_misc/integration_test_models_instance1/parrot.json @@ -10,7 +10,7 @@ "associations": { "unique_person": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "person", "targetKey": "person_id", "keysIn": "parrot", diff --git a/test/integration_test_misc/integration_test_models_instance1/parrot_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance1/parrot_instance1_adapter.json index 071738b9..d9325bab 100644 --- a/test/integration_test_misc/integration_test_models_instance1/parrot_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/parrot_instance1_adapter.json @@ -11,7 +11,7 @@ "associations": { "unique_person": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "person", "targetKey": "person_id", "keysIn": "parrot", diff --git a/test/integration_test_misc/integration_test_models_instance1/parrot_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance1/parrot_instance2_adapter.json index a0b76a6d..152944f0 100644 --- a/test/integration_test_misc/integration_test_models_instance1/parrot_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/parrot_instance2_adapter.json @@ -12,7 +12,7 @@ "associations": { "unique_person": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "person", "targetKey": "person_id", "keysIn": "parrot", diff --git a/test/integration_test_misc/integration_test_models_instance1/person.json b/test/integration_test_misc/integration_test_models_instance1/person.json index e69a8eae..9daf5061 100644 --- a/test/integration_test_misc/integration_test_models_instance1/person.json +++ b/test/integration_test_misc/integration_test_models_instance1/person.json @@ -9,7 +9,7 @@ "associations": { "dogs": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "dog", "targetKey": "person_id", "keysIn": "dog", @@ -17,7 +17,7 @@ }, "unique_parrot": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "parrot", "targetKey": "person_id", "keysIn": "parrot", diff --git a/test/integration_test_misc/integration_test_models_instance1/person_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance1/person_instance1_adapter.json index bb6369ac..2767744c 100644 --- a/test/integration_test_misc/integration_test_models_instance1/person_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/person_instance1_adapter.json @@ -10,7 +10,7 @@ "associations": { "dogs": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "dog", "targetKey": "person_id", "keysIn": "dog", @@ -18,7 +18,7 @@ }, "unique_parrot": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "parrot", "targetKey": "person_id", "keysIn": "parrot", diff --git a/test/integration_test_misc/integration_test_models_instance1/person_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance1/person_instance2_adapter.json index d0b633ae..39d27ab9 100644 --- a/test/integration_test_misc/integration_test_models_instance1/person_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance1/person_instance2_adapter.json @@ -11,7 +11,7 @@ "associations": { "dogs": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "dog", "targetKey": "person_id", "keysIn": "dog", @@ -19,7 +19,7 @@ }, "unique_parrot": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "parrot", "targetKey": "person_id", "keysIn": "parrot", diff --git a/test/integration_test_misc/integration_test_models_instance1/river.json b/test/integration_test_misc/integration_test_models_instance1/river.json index 62c70d00..aa2c11a9 100644 --- a/test/integration_test_misc/integration_test_models_instance1/river.json +++ b/test/integration_test_misc/integration_test_models_instance1/river.json @@ -20,7 +20,7 @@ }, "cities": { "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "city", "targetStorageType": "cassandra", "sourceKey": "city_ids", diff --git a/test/integration_test_misc/integration_test_models_instance1/sq_author.json b/test/integration_test_misc/integration_test_models_instance1/sq_author.json index 39e33d06..79e6d1b2 100644 --- a/test/integration_test_misc/integration_test_models_instance1/sq_author.json +++ b/test/integration_test_misc/integration_test_models_instance1/sq_author.json @@ -12,7 +12,7 @@ "associations": { "books": { "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance1/sq_book.json b/test/integration_test_misc/integration_test_models_instance1/sq_book.json index 8d783766..232962b8 100644 --- a/test/integration_test_misc/integration_test_models_instance1/sq_book.json +++ b/test/integration_test_misc/integration_test_models_instance1/sq_book.json @@ -13,7 +13,7 @@ "associations": { "authors": { "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/integration_test_misc/integration_test_models_instance1/tracker.json b/test/integration_test_misc/integration_test_models_instance1/tracker.json index 95782ad1..3b31af63 100644 --- a/test/integration_test_misc/integration_test_models_instance1/tracker.json +++ b/test/integration_test_misc/integration_test_models_instance1/tracker.json @@ -9,7 +9,7 @@ "associations": { "unique_animal": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "animal", "targetKey": "animal_id", "keysIn": "tracker", diff --git a/test/integration_test_misc/integration_test_models_instance1/transcript_count.json b/test/integration_test_misc/integration_test_models_instance1/transcript_count.json index 25be80a8..744a432b 100644 --- a/test/integration_test_misc/integration_test_models_instance1/transcript_count.json +++ b/test/integration_test_misc/integration_test_models_instance1/transcript_count.json @@ -12,7 +12,7 @@ "associations": { "individual": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "individual", "targetKey": "individual_id", "keysIn": "transcript_count", @@ -20,7 +20,7 @@ }, "aminoacidsequence": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "aminoacidsequence", "targetKey": "aminoacidsequence_id", "keysIn": "transcript_count", diff --git a/test/integration_test_misc/integration_test_models_instance2/accession.json b/test/integration_test_misc/integration_test_models_instance2/accession.json index 6266e614..61ea24ca 100644 --- a/test/integration_test_misc/integration_test_models_instance2/accession.json +++ b/test/integration_test_misc/integration_test_models_instance2/accession.json @@ -14,7 +14,7 @@ "location": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Location", "targetKey": "locationId", "keysIn": "Accession", @@ -25,7 +25,7 @@ "measurements": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Measurement", "targetKey": "accessionId", "keysIn": "Measurement", diff --git a/test/integration_test_misc/integration_test_models_instance2/author.json b/test/integration_test_misc/integration_test_models_instance2/author.json index 3f1c0fdb..261dc9d8 100644 --- a/test/integration_test_misc/integration_test_models_instance2/author.json +++ b/test/integration_test_misc/integration_test_models_instance2/author.json @@ -13,7 +13,7 @@ "associations":{ "books":{ "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/book.json b/test/integration_test_misc/integration_test_models_instance2/book.json index 471e8c07..1625a50a 100644 --- a/test/integration_test_misc/integration_test_models_instance2/book.json +++ b/test/integration_test_misc/integration_test_models_instance2/book.json @@ -13,7 +13,7 @@ "associations":{ "authors":{ "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/dog.json b/test/integration_test_misc/integration_test_models_instance2/dog.json index 70227002..f354c1cb 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dog.json +++ b/test/integration_test_misc/integration_test_models_instance2/dog.json @@ -10,7 +10,7 @@ "associations": { "person": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "person", "targetKey": "person_id", "keysIn": "dog", diff --git a/test/integration_test_misc/integration_test_models_instance2/dog_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance2/dog_instance1_adapter.json index bfeba25c..a57a7931 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dog_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/dog_instance1_adapter.json @@ -12,7 +12,7 @@ "associations": { "person": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "person", "targetKey": "person_id", "keysIn": "dog", diff --git a/test/integration_test_misc/integration_test_models_instance2/dog_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance2/dog_instance2_adapter.json index 1fd8a6c2..73f90529 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dog_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/dog_instance2_adapter.json @@ -11,7 +11,7 @@ "associations": { "person": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "person", "targetKey": "person_id", "keysIn": "dog", diff --git a/test/integration_test_misc/integration_test_models_instance2/location.json b/test/integration_test_misc/integration_test_models_instance2/location.json index 0afe8ba6..b0cce4f8 100644 --- a/test/integration_test_misc/integration_test_models_instance2/location.json +++ b/test/integration_test_misc/integration_test_models_instance2/location.json @@ -14,7 +14,7 @@ "accessions": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Accession", "targetKey": "locationId", "keysIn": "Accession", diff --git a/test/integration_test_misc/integration_test_models_instance2/measurement.json b/test/integration_test_misc/integration_test_models_instance2/measurement.json index bcae417d..d6899c8d 100644 --- a/test/integration_test_misc/integration_test_models_instance2/measurement.json +++ b/test/integration_test_misc/integration_test_models_instance2/measurement.json @@ -13,7 +13,7 @@ "accession": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Accession", "targetKey": "accessionId", "keysIn": "Measurement", diff --git a/test/integration_test_misc/integration_test_models_instance2/parrot.json b/test/integration_test_misc/integration_test_models_instance2/parrot.json index 9921ef6a..eb753066 100644 --- a/test/integration_test_misc/integration_test_models_instance2/parrot.json +++ b/test/integration_test_misc/integration_test_models_instance2/parrot.json @@ -10,7 +10,7 @@ "associations": { "unique_person": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "person", "targetKey": "person_id", "keysIn": "parrot", diff --git a/test/integration_test_misc/integration_test_models_instance2/parrot_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance2/parrot_instance1_adapter.json index b8d9bc5c..bdc6200f 100644 --- a/test/integration_test_misc/integration_test_models_instance2/parrot_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/parrot_instance1_adapter.json @@ -12,7 +12,7 @@ "associations": { "unique_person": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "person", "targetKey": "person_id", "keysIn": "parrot", diff --git a/test/integration_test_misc/integration_test_models_instance2/parrot_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance2/parrot_instance2_adapter.json index bed23c26..dc8903e0 100644 --- a/test/integration_test_misc/integration_test_models_instance2/parrot_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/parrot_instance2_adapter.json @@ -11,7 +11,7 @@ "associations": { "unique_person": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "person", "targetKey": "person_id", "keysIn": "parrot", diff --git a/test/integration_test_misc/integration_test_models_instance2/person.json b/test/integration_test_misc/integration_test_models_instance2/person.json index e69a8eae..9daf5061 100644 --- a/test/integration_test_misc/integration_test_models_instance2/person.json +++ b/test/integration_test_misc/integration_test_models_instance2/person.json @@ -9,7 +9,7 @@ "associations": { "dogs": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "dog", "targetKey": "person_id", "keysIn": "dog", @@ -17,7 +17,7 @@ }, "unique_parrot": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "parrot", "targetKey": "person_id", "keysIn": "parrot", diff --git a/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json b/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json index 4f5e1c04..bb56388f 100644 --- a/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/person_instance1_adapter.json @@ -11,7 +11,7 @@ "associations": { "dogs": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "dog", "targetKey": "person_id", "keysIn": "dog", @@ -19,7 +19,7 @@ }, "unique_parrot": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "parrot", "targetKey": "person_id", "keysIn": "parrot", diff --git a/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json b/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json index f81e380b..698341c9 100644 --- a/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/person_instance2_adapter.json @@ -10,7 +10,7 @@ "associations": { "dogs": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "dog", "targetKey": "person_id", "keysIn": "dog", @@ -18,7 +18,7 @@ }, "unique_parrot": { "type": "one_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "parrot", "targetKey": "person_id", "keysIn": "parrot", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json index 7716d330..03f834b6 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_author_adapter.json @@ -14,7 +14,7 @@ "associations":{ "books":{ "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json b/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json index cd6b4353..057a1adf 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_author_ddm.json @@ -13,7 +13,7 @@ "associations":{ "books":{ "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json index 0b09df09..46c121e4 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_author_zendro_adapter.json @@ -15,7 +15,7 @@ "associations":{ "books":{ "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json index c7cb140b..6a36f9b6 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_book_adapter.json @@ -14,7 +14,7 @@ "associations":{ "authors":{ "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json b/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json index 3115986c..59b38fa4 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_book_ddm.json @@ -13,7 +13,7 @@ "associations":{ "authors":{ "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json b/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json index bd83300a..607bd833 100644 --- a/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json +++ b/test/integration_test_misc/integration_test_models_instance2/sq_book_zendro_adapter.json @@ -15,7 +15,7 @@ "associations":{ "authors":{ "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "sq_author", "targetKey": "book_ids", "sourceKey": "author_ids", diff --git a/test/mocha_unit.test.js b/test/mocha_unit.test.js index 9eb3c6a4..7cb368ca 100644 --- a/test/mocha_unit.test.js +++ b/test/mocha_unit.test.js @@ -1356,7 +1356,7 @@ describe("Parse associations", function () { to_one: [ { type: "many_to_one", - implementation: "foreignkey", + implementation: "foreignkeys", target: "individual", targetKey: "individual_id", targetKey_cp: "Individual_id", @@ -1386,7 +1386,7 @@ describe("Parse associations", function () { associations: [ { type: "many_to_one", - implementation: "foreignkey", + implementation: "foreignkeys", target: "individual", targetKey: "individual_id", keysIn: "transcript_count", @@ -1417,7 +1417,7 @@ describe("Parse associations", function () { to_many: [ { type: "one_to_many", - implementation: "foreignkey", + implementation: "foreignkeys", target: "transcript_count", keysIn: "transcript_count", targetKey: "individual_id", @@ -1446,7 +1446,7 @@ describe("Parse associations", function () { associations: [ { type: "one_to_many", - implementation: "foreignkey", + implementation: "foreignkeys", target: "transcript_count", keysIn: "transcript_count", targetKey: "individual_id", @@ -1544,7 +1544,7 @@ describe("Parse associations", function () { to_many: [ { type: "one_to_many", - implementation: "foreignkey", + implementation: "foreignkeys", target: "Dog", targetKey: "personId", targetKey_cp: "PersonId", @@ -1597,7 +1597,7 @@ describe("Parse associations", function () { associations: [ { type: "one_to_many", - implementation: "foreignkey", + implementation: "foreignkeys", target: "Dog", targetKey: "personId", keysIn: "Dog", @@ -1633,7 +1633,7 @@ describe("Parse associations", function () { to_one: [ { type: "many_to_one", - implementation: "foreignkey", + implementation: "foreignkeys", target: "Person", targetKey: "personId", targetKey_cp: "PersonId", @@ -1656,7 +1656,7 @@ describe("Parse associations", function () { }, { type: "many_to_one", - implementation: "foreignkey", + implementation: "foreignkeys", target: "Researcher", targetKey: "researcherId", targetKey_cp: "ResearcherId", @@ -1688,7 +1688,7 @@ describe("Parse associations", function () { associations: [ { type: "many_to_one", - implementation: "foreignkey", + implementation: "foreignkeys", target: "Person", targetKey: "personId", keysIn: "Dog", @@ -1698,7 +1698,7 @@ describe("Parse associations", function () { }, { type: "many_to_one", - implementation: "foreignkey", + implementation: "foreignkeys", target: "Researcher", targetKey: "researcherId", keysIn: "Dog", diff --git a/test/unit_test_misc/data_models.js b/test/unit_test_misc/data_models.js index 30006a03..c0ad755c 100644 --- a/test/unit_test_misc/data_models.js +++ b/test/unit_test_misc/data_models.js @@ -11,7 +11,7 @@ module.exports.transcript_count = { "associations":{ "individual":{ "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "individual", "targetKey" : "individual_id", "keysIn": "transcript_count", @@ -29,7 +29,7 @@ module.exports.individual = { "associations": { "transcript_counts": { "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "transcript_count", "keysIn": "transcript_count", "targetKey" : "individual_id", @@ -68,7 +68,7 @@ module.exports.person = { "associations":{ "dogs":{ "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Dog", "targetKey" : "personId", "keysIn": "Dog", @@ -108,7 +108,7 @@ module.exports.book = { }, "publisher" : { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Publisher", "targetKey" : "publisherId", "keysIn": "Book", @@ -137,7 +137,7 @@ module.exports.researcher = { }, "dog":{ "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Dog", "targetKey": "researcherId", "keysIn": "Dog", @@ -159,7 +159,7 @@ module.exports.specie = { "associations":{ "projects" : { "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Project", "targetKey" : "specieId", "keysIn": "Project", @@ -179,7 +179,7 @@ module.exports.dog = { "associations" : { "person" : { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Person", "targetKey" : "personId", "keysIn": "Dog", @@ -189,7 +189,7 @@ module.exports.dog = { }, "researcher":{ "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Researcher", "targetKey": "researcherId", "keysIn": "Dog", @@ -217,7 +217,7 @@ module.exports.assoc_through_project_researcher = { module.exports.assoc_dogs_researcher = { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Researcher", "targetKey": "researcherId", "keysIn": "Dog", @@ -250,7 +250,7 @@ module.exports.inDiVIdual_camelcase = { "associations": { "transcriptCounts": { "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "transcriptCount", "targetKey" : "individual_id", "keysIn": "transcriptCount", @@ -274,7 +274,7 @@ module.exports.transcriptCount_camelcase = { "associations":{ "inDiVIdual":{ "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "inDiVIdual", "targetKey" : "individual_id", "keysIn": "transcriptCount", @@ -296,7 +296,7 @@ module.exports.transcriptCount_indiv= { "associations":{ "individual":{ "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Individual", "targetKey" : "individual_id", "keysIn": "transcriptCount", @@ -319,7 +319,7 @@ module.exports.dog_owner = { "associations" : { "owner" : { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Person", "targetKey" : "owner_id_test", "keysIn": "Dog", @@ -329,7 +329,7 @@ module.exports.dog_owner = { }, "keeper":{ "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Researcher", "targetKey": "keeperId", "keysIn": "Dog", @@ -351,7 +351,7 @@ module.exports.person_indices = { "associations":{ "dogs":{ "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Dog", "targetKey" : "personId", "keysIn": "Dog", @@ -386,7 +386,7 @@ module.exports.person_externalIds = { "associations":{ "dogs":{ "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Dog", "targetKey" : "personId", "keysIn": "Dog", @@ -421,7 +421,7 @@ module.exports.academicTeam = { "associations":{ "members":{ "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Researcher", "targetKey" : "academicTeamId", "keysIn": "Researcher", @@ -445,7 +445,7 @@ module.exports.person_date = { "associations":{ "dogs":{ "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Dog", "targetKey" : "personId", "keysIn": "Dog", @@ -455,7 +455,7 @@ module.exports.person_date = { "patients":{ "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Dog", "targetKey" : "doctor_Id", "keysIn": "Dog", @@ -500,7 +500,7 @@ module.exports.book_authors = { }, "publisher" : { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Publisher", "targetKey" : "publisherId", "keysIn" : "Book", @@ -527,7 +527,7 @@ module.exports.person_description = { "associations":{ "dogs":{ "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Dog", "targetKey" : "personId", "keysIn": "Dog", @@ -562,7 +562,7 @@ module.exports.person_description_optional = { "associations":{ "dogs":{ "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Dog", "targetKey" : "personId", "keysIn": "Dog", @@ -593,7 +593,7 @@ module.exports.academic_Team = { "associations":{ "members":{ "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Researcher", "targetKey" : "AcademicTeam_Id", "keysIn": "Researcher", @@ -615,7 +615,7 @@ module.exports.dog_one_assoc = { "associations" : { "owner" : { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Person", "targetKey" : "personId", "keysIn" : "Dog", @@ -637,7 +637,7 @@ module.exports.person_one_assoc = { "associations" : { "unique_pet" :{ "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Dog", "targetKey": "personId", "keysIn": "Dog", @@ -659,7 +659,7 @@ module.exports.book_extendedIds = { "associations": { "author": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Person", "targetKey": "internalPersonId", "keysIn": "Book", @@ -685,7 +685,7 @@ module.exports.author_foreignKeyArray = { "associations":{ "books":{ "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "book", "targetKey": "author_ids", "sourceKey": "book_ids", @@ -712,7 +712,7 @@ module.exports.author_zendro_remote = { "associations":{ "books":{ "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "post_book", "targetKey": "author_ids", "sourceKey": "book_ids", @@ -738,7 +738,7 @@ module.exports.author_ddm_array_fk ={ "associations":{ "books":{ "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", @@ -765,7 +765,7 @@ module.exports.author_sql_adapter_array_fk ={ "associations":{ "books":{ "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", @@ -794,7 +794,7 @@ module.exports.author_zendro_adapter_array_fk ={ "associations":{ "books":{ "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "sq_book", "targetKey": "author_ids", "sourceKey": "book_ids", diff --git a/test/unit_test_misc/data_models_cassandra.js b/test/unit_test_misc/data_models_cassandra.js index 019a5fb0..7f81f515 100644 --- a/test/unit_test_misc/data_models_cassandra.js +++ b/test/unit_test_misc/data_models_cassandra.js @@ -16,7 +16,7 @@ module.exports.city = { "associations": { "rivers": { "type": "many_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "river", "targetStorageType": "sql", "sourceKey": "river_ids", @@ -41,7 +41,7 @@ module.exports.incident = { "instants": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Instant", "targetKey": "incident_assoc_id", "keysIn" : "Instant", @@ -49,7 +49,7 @@ module.exports.incident = { }, "town": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "capital", "targetKey": "capital_id", "keysIn" : "Incident", @@ -76,7 +76,7 @@ module.exports.dist_incident = { "dist_instants": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Dist_instant", "targetKey": "incident_assoc_id", "keysIn" : "Dist_instant", @@ -103,7 +103,7 @@ module.exports.dist_instant_instance1 = { "dist_instants": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Dist_instant", "targetKey": "incident_assoc_id", "keysIn": "Dist_instant", diff --git a/test/unit_test_misc/data_models_distributed.js b/test/unit_test_misc/data_models_distributed.js index b2008902..89a4c349 100644 --- a/test/unit_test_misc/data_models_distributed.js +++ b/test/unit_test_misc/data_models_distributed.js @@ -24,7 +24,7 @@ module.exports.book = { }, "publisher" : { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "publi_sher", "targetKey" : "publisher_id", "keysIn" : "Book", @@ -60,7 +60,7 @@ module.exports.book_ddm = }, "publisher" : { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "publi_sher", "targetKey" : "publisher_id", "keysIn" : "Book", @@ -95,7 +95,7 @@ module.exports.person_ddm = { "company":{ "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "publi_sher", "targetKey": "companyId", "keysIn": "Person", @@ -104,7 +104,7 @@ module.exports.person_ddm = { "dogs" :{ "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Dog", "targetKey": "personId", "keysIn": "Dog", @@ -113,7 +113,7 @@ module.exports.person_ddm = { "parrot" :{ "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Parrot", "targetKey": "personId", "keysIn": "Parrot", @@ -137,7 +137,7 @@ module.exports.dog_ddm = { "associations" : { "owner" : { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Person", "targetKey" : "personId", "keysIn" : "Dog", @@ -163,7 +163,7 @@ module.exports.dog_ddm = { "associations": { "works": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Book", "targetKey": "internalPersonId", "keysIn": "Book", @@ -210,7 +210,7 @@ module.exports.dog_ddm = { "associations": { "author": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Person", "targetKey": "internalPersonId", "keysIn": "Book", @@ -233,7 +233,7 @@ module.exports.dog_ddm_integration_test = { "associations": { "person": { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "person", "targetKey" : "person_id", "keysIn": "dog", @@ -259,7 +259,7 @@ module.exports.dog_zendro_adapter_integration_test = "associations": { "person": { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "person", "targetKey" : "person_id", "keysIn": "dog", diff --git a/test/unit_test_misc/data_models_extendedId.js b/test/unit_test_misc/data_models_extendedId.js index 497182e4..1080e3d6 100644 --- a/test/unit_test_misc/data_models_extendedId.js +++ b/test/unit_test_misc/data_models_extendedId.js @@ -13,7 +13,7 @@ module.exports.book_adapter = { "associations": { "author": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Person", "targetKey": "internalPersonId", "keysIn": "Book", @@ -40,7 +40,7 @@ module.exports.book_ddm = { "associations": { "author": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Person", "targetKey": "internalPersonId", "keysIn": "Book", @@ -67,7 +67,7 @@ module.exports.person_adapter = { "associations": { "works": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Book", "targetKey": "internalPersonId", "keysIn": "Book", @@ -95,7 +95,7 @@ module.exports.person_ddm = { "associations": { "works": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Book", "targetKey": "internalPersonId", "keysIn": "Book", diff --git a/test/unit_test_misc/data_models_generic.js b/test/unit_test_misc/data_models_generic.js index 7ce205aa..2ab8f97f 100644 --- a/test/unit_test_misc/data_models_generic.js +++ b/test/unit_test_misc/data_models_generic.js @@ -23,7 +23,7 @@ module.exports.personSql_toMany_dogGeneric = { "associations":{ "dogs":{ "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Dog", "targetKey" : "personId", "keysIn": "Dog", @@ -44,7 +44,7 @@ module.exports.dogGeneric_toOne_personSql = { "associations" : { "owner" : { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Person", "targetKey" : "personId", "keysIn": "Dog", @@ -69,7 +69,7 @@ module.exports.personSql_toOne_hometownGeneric = { "associations":{ "unique_homeTown":{ "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Hometown", "targetKey" : "hometownId", "keysIn": "Person", @@ -92,7 +92,7 @@ module.exports.hometownGeneric_toMany_personSql = { "associations" : { "people" : { "type" : "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Person", "targetKey" : "hometownId", "keysIn": "Person", diff --git a/test/unit_test_misc/data_models_generic_webservice.js b/test/unit_test_misc/data_models_generic_webservice.js index 59ec5ab0..65792cf5 100644 --- a/test/unit_test_misc/data_models_generic_webservice.js +++ b/test/unit_test_misc/data_models_generic_webservice.js @@ -11,7 +11,7 @@ module.exports.book = "associations": { "publisher" : { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "publi_sher", "targetKey": "publisher_id", "keysIn": "book", @@ -20,7 +20,7 @@ module.exports.book = "authors": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Person", "targetKey": "person_id", "sourceKey": "book_id", @@ -43,7 +43,7 @@ module.exports.person = "associations" : { "works" : { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "book", "targetKey": "book_id", "sourceKey": "person_id", @@ -52,7 +52,7 @@ module.exports.person = "company":{ "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "publi_sher", "targetKey": "companyId", "keysIn": "Person", @@ -74,7 +74,7 @@ module.exports.publisher = "associations": { "publications" : { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "book", "targetKey": "publisher_id", "keysIn": "book", @@ -83,7 +83,7 @@ module.exports.publisher = "director":{ "type":"many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Person", "targetKey": "companyId", "keysIn": "Person", diff --git a/test/unit_test_misc/data_models_mongodb.js b/test/unit_test_misc/data_models_mongodb.js index f8664955..dcf44d0c 100644 --- a/test/unit_test_misc/data_models_mongodb.js +++ b/test/unit_test_misc/data_models_mongodb.js @@ -16,7 +16,7 @@ module.exports.animal = { associations: { farm: { type: "many_to_one", - implementation: "foreignkey", + implementation: "foreignkeys", target: "farm", targetKey: "farm_id", keysIn: "animal", @@ -25,7 +25,7 @@ module.exports.animal = { }, food: { type: "many_to_many", - implementation: "foreignkey", + implementation: "foreignkeys", target: "food", targetKey: "animal_ids", sourceKey: "food_ids", @@ -60,7 +60,7 @@ module.exports.dist_animal_instance1 = { associations: { dist_farm: { type: "many_to_one", - implementation: "foreignkey", + implementation: "foreignkeys", target: "dist_farm", targetKey: "farm_id", keysIn: "dist_animal", diff --git a/test/unit_test_misc/data_models_refactoring.js b/test/unit_test_misc/data_models_refactoring.js index 342e8c2b..f0724f1e 100644 --- a/test/unit_test_misc/data_models_refactoring.js +++ b/test/unit_test_misc/data_models_refactoring.js @@ -13,7 +13,7 @@ module.exports.accession = { "individuals": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Individual", "targetKey": "accessionId", "keysIn" : "Individual", @@ -23,7 +23,7 @@ module.exports.accession = { "location": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Location", "targetKey": "locationId", "keysIn" : "Accession", @@ -34,7 +34,7 @@ module.exports.accession = { "measurements": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Measurement", "targetKey": "accessionId", "keysIn" : "Measurement", @@ -63,7 +63,7 @@ module.exports.accession_ddm = { "individuals": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Individual", "targetKey": "accessionId", "keysIn" : "Individual", @@ -73,7 +73,7 @@ module.exports.accession_ddm = { "location": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Location", "targetKey": "locationId", "keysIn" : "Accession", @@ -84,7 +84,7 @@ module.exports.accession_ddm = { "measurements": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Measurement", "targetKey": "accessionId", "keysIn" : "Measurement", @@ -114,7 +114,7 @@ module.exports.accession_sql_adapter = { "individuals": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Individual", "targetKey": "accessionId", "keysIn" : "Individual", @@ -124,7 +124,7 @@ module.exports.accession_sql_adapter = { "location": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Location", "targetKey": "locationId", "keysIn" : "Accession", @@ -135,7 +135,7 @@ module.exports.accession_sql_adapter = { "measurements": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Measurement", "targetKey": "accession_id", "keysIn" : "Measurement", @@ -165,7 +165,7 @@ module.exports.accession_zendro_adapter = { "individuals": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Individual", "targetKey": "accessionId", "keysIn" : "Individual", @@ -176,7 +176,7 @@ module.exports.accession_zendro_adapter = { "location": { "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Location", "targetKey": "locationId", "keysIn" : "Accession", @@ -187,7 +187,7 @@ module.exports.accession_zendro_adapter = { "measurements": { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Measurement", "targetKey": "accession_id", "keysIn" : "Measurement", diff --git a/test/unit_test_misc/data_models_zendro.js b/test/unit_test_misc/data_models_zendro.js index ccdd0832..02598f44 100644 --- a/test/unit_test_misc/data_models_zendro.js +++ b/test/unit_test_misc/data_models_zendro.js @@ -22,7 +22,7 @@ module.exports.book = { }, "publisher" : { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "publi_sher", "targetKey" : "publisher_id", "keysIn" : "Book", @@ -56,7 +56,7 @@ module.exports.person = { "company":{ "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "publi_sher", "targetKey": "companyId", "keysIn": "Person", @@ -79,7 +79,7 @@ module.exports.dog_one_assoc = { "associations" : { "owner" : { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Person", "targetKey" : "personId", "keysIn" : "Dog", @@ -88,7 +88,7 @@ module.exports.dog_one_assoc = { "veterinarian" : { "type" : "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target" : "Person", "targetKey" : "veterinarianId", "keysIn" : "Dog", @@ -111,7 +111,7 @@ module.exports.person_one_assoc = { "associations" : { "unique_pet" :{ "type": "many_to_one", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Dog", "targetKey": "personId", "keysIn": "Dog", @@ -120,7 +120,7 @@ module.exports.person_one_assoc = { "patients" : { "type": "one_to_many", - "implementation": "foreignkey", + "implementation": "foreignkeys", "target": "Dog", "targetKey": "veterinarianId", "keysIn": "Dog", diff --git a/test/unit_test_misc/test-describe/distributed-models.js b/test/unit_test_misc/test-describe/distributed-models.js index 0fa81eb9..587e8e72 100644 --- a/test/unit_test_misc/test-describe/distributed-models.js +++ b/test/unit_test_misc/test-describe/distributed-models.js @@ -338,7 +338,7 @@ const definition = { }, company: { type: 'many_to_one', - implementation: 'foreignkey', + implementation: 'foreignkeys', target: 'publi_sher', targetKey: 'companyId', keysIn: 'Person', @@ -346,7 +346,7 @@ const definition = { }, dogs: { type: 'one_to_many', - implementation: 'foreignkey', + implementation: 'foreignkeys', target: 'Dog', targetKey: 'personId', keysIn: 'Dog', @@ -354,7 +354,7 @@ const definition = { }, parrot: { type: 'many_to_one', - implementation: 'foreignkey', + implementation: 'foreignkeys', target: 'Parrot', targetKey: 'personId', keysIn: 'Parrot', @@ -383,7 +383,7 @@ const definition = { associations: { owner: { type: 'many_to_one', - implementation: 'foreignkey', + implementation: 'foreignkeys', target: 'Person', targetKey: 'personId', keysIn: 'Dog', diff --git a/test/unit_test_misc/test-describe/zendro-servers.js b/test/unit_test_misc/test-describe/zendro-servers.js index 59f69271..54264fbc 100644 --- a/test/unit_test_misc/test-describe/zendro-servers.js +++ b/test/unit_test_misc/test-describe/zendro-servers.js @@ -270,7 +270,7 @@ const definition = { }, company: { type: 'many_to_one', - implementation: 'foreignkey', + implementation: 'foreignkeys', target: 'publi_sher', targetKey: 'companyId', keysIn: 'Person', From ed93d3e4a2a24338c05f4e73587966b51148e622 Mon Sep 17 00:00:00 2001 From: coeit Date: Thu, 17 Jun 2021 12:47:30 +0200 Subject: [PATCH 12/18] Merge branch 'master' into refactor-assoc-types --- README.md | 15 + funks.js | 45 +- lib/generators-aux.js | 2 + .../data_models_storage_config2.json | 8 + .../docker-compose-test.yml | 19 + test/integration_test_misc/import/movie.csv | 7 + .../actor.json | 27 + .../director.json | 24 + .../dist_director.json | 20 + .../dist_director_instance1.json | 22 + .../dist_movie.json | 27 + .../dist_movie_instance1.json | 28 + .../movie.json | 42 + .../review.json | 23 + test/mocha_integration.test.js | 130 ++- test/mocha_integration_neo4j.test.js | 998 ++++++++++++++++++ test/mocha_unit.test.js | 176 ++- test/testenv_cli.sh | 7 +- test/testenv_docker_up.sh | 2 +- test/testenv_remove.sh | 2 +- test/unit_test_misc/data_models_neo4j.js | 70 ++ .../test-describe/amazonS3-unittest.js | 2 +- .../test-describe/cassandra-storagetype.js | 1 + .../test-describe/distributed-models.js | 2 + .../test-describe/handle-error-ddm.js | 2 + .../test-describe/neo4j-unittest.js | 634 +++++++++++ .../test-describe/trino-unittest.js | 2 +- views/create-amazonS3-adapter.ejs | 6 +- views/create-distributed-model.ejs | 2 + views/create-models-amazonS3.ejs | 2 +- views/create-models-neo4j.ejs | 530 ++++++++++ views/create-models-trino.ejs | 2 +- views/create-neo4j-adapter.ejs | 482 +++++++++ views/create-trino-adapter.ejs | 2 +- views/includes/bulkAssociations-models.ejs | 37 + .../create-adapter-fields-mutations.ejs | 87 ++ .../create-models-fieldMutations-neo4j.ejs | 97 ++ 37 files changed, 3459 insertions(+), 125 deletions(-) create mode 100644 test/integration_test_misc/import/movie.csv create mode 100644 test/integration_test_misc/integration_test_models_instance2/actor.json create mode 100644 test/integration_test_misc/integration_test_models_instance2/director.json create mode 100644 test/integration_test_misc/integration_test_models_instance2/dist_director.json create mode 100644 test/integration_test_misc/integration_test_models_instance2/dist_director_instance1.json create mode 100644 test/integration_test_misc/integration_test_models_instance2/dist_movie.json create mode 100644 test/integration_test_misc/integration_test_models_instance2/dist_movie_instance1.json create mode 100644 test/integration_test_misc/integration_test_models_instance2/movie.json create mode 100644 test/integration_test_misc/integration_test_models_instance2/review.json create mode 100644 test/mocha_integration_neo4j.test.js create mode 100644 test/unit_test_misc/data_models_neo4j.js create mode 100644 test/unit_test_misc/test-describe/neo4j-unittest.js create mode 100644 views/create-models-neo4j.ejs create mode 100644 views/create-neo4j-adapter.ejs create mode 100644 views/includes/create-models-fieldMutations-neo4j.ejs diff --git a/README.md b/README.md index 1b121bf4..c8c76c9b 100644 --- a/README.md +++ b/README.md @@ -316,3 +316,18 @@ Example: ## Testing For relevant files see `package.json` (section scripts), directories `.test` and `docker`. Test framework is `mocha` and `chai`. + +## Contributions +Zendro is the product of a joint effort between the Forschungszentrum Jülich, Germany and the Comisión Nacional para el Conocimiento y Uso de la Biodiversidad, México, to generate a tool that allows efficiently building data warehouses capable of dealing with diverse data generated by different research groups in the context of the FAIR principles and multidisciplinary projects. The name Zendro comes from the words Zenzontle and Drossel, which are Mexican and German words denoting a mockingbird, a bird capable of “talking” different languages, similar to how Zendro can connect your data warehouse from any programming language or data analysis pipeline. + +### Zendro contributors in alphabetical order +Francisca Acevedo1, Vicente Arriaga1, Katja Dohm3, Constantin Eiteneuer2, Sven Fahrner2, Frank Fischer4, Asis Hallab2, Alicia Mastretta-Yanes1, Roland Pieruschka2, Alejandro Ponce1, Yaxal Ponce2, Francisco Ramírez1, Irene Ramos1, Bernardo Terroba1, Tim Rehberg3, Verónica Suaste1, Björn Usadel2, David Velasco2, Thomas Voecking3, Dan Wang2 + +#### Author affiliations +1. CONABIO - Comisión Nacional para el Conocimiento y Uso de la Biodiversidad, México +2. Forschungszentrum Jülich - Germany +3. auticon - www.auticon.com +4. InterTech - www.intertech.de + +### Zendro author contributions +Asis Hallab and Alicia Mastretta-Yanes coordinated the project. Asis Hallab designed the software. Programming of code generators, the browser based single page application interface, and the GraphQL application programming interface was done by Katja Dohm, Constantin Eiteneuer, Francisco Ramírez, Tim Rehberg, Veronica Suaste, David Velasco, Thomas Voecking, and Dan Wang. Counselling and use case definitions were contributed by Francisca Acevedo, Vicente Arriaga, Frank Fischer, Roland Pieruschka, Alejandro Ponce, Irene Ramos, and Björn Usadel. User experience and application of Zendro on data management projects was carried out by Asis Hallab, Alicia Mastretta-Yanes, Yaxal Ponce, Irene Ramos, Verónica Suaste, and David Velasco. Logo design was made by Bernardo Terroba. diff --git a/funks.js b/funks.js index 1f966cc3..307fa953 100644 --- a/funks.js +++ b/funks.js @@ -462,8 +462,8 @@ writeAcls = async function (dir_write, models, adapters) { //set file name let file_name = dir_write + "/acl_rules.js"; //set names - const modelsNames = models.map(item => item[0]); - let adminModelsNames = ['role', 'user', 'role_to_user']; + const modelsNames = models.map((item) => item[0]); + let adminModelsNames = ["role", "user", "role_to_user"]; //generate await generateSection( "acl_rules", @@ -1000,6 +1000,7 @@ generateSections = async function (sections, opts, dir_write) { case "models-mongodb": case "models-amazonS3": case "models-trino": + case "models-neo4j": //adapters case "sql-adapter": case "zendro-adapters": @@ -1008,6 +1009,7 @@ generateSections = async function (sections, opts, dir_write) { case "mongodb-adapter": case "amazonS3-adapter": case "trino-adapter": + case "neo4j-adapter": file_name = dir_write + "/" + section.dir + "/" + section.fileName + ".js"; break; @@ -1113,6 +1115,7 @@ getStorageType = function (dataModel) { case "amazon-s3": case "trino": case "presto": + case "neo4j": //adapters case "sql-adapter": case "ddm-adapter": @@ -1123,6 +1126,7 @@ getStorageType = function (dataModel) { case "amazon-s3-adapter": case "trino-adapter": case "presto-adapter": + case "neo4j-adapter": //ok break; @@ -1134,8 +1138,8 @@ getStorageType = function (dataModel) { `ERROR: The attribute 'storageType' has an invalid value. \n One of the following types is expected: [sql, distributed-data-model, zendro-server, generic, sql-adapter, ddm-adapter, zendro-webservice-adapter, generic-adapter, - cassandra, mongodb, amazon-s3, trino, presto, cassandra-adapter, mongodb-adapter, - amazon-s3-adapter, trino-adapter, presto-adapter]. + cassandra, mongodb, amazon-s3, trino, presto, neo4j, cassandra-adapter, mongodb-adapter, + amazon-s3-adapter, trino-adapter, presto-adapter, neo4j-adapter]. But '${dataModel.storageType}' was obtained on ${ dataModel.adapterName !== undefined ? "adapter" : "model" } '${ @@ -1187,6 +1191,7 @@ module.exports.generateCode = async function (json_dir, dir_write, options) { "models/amazonS3", "models/trino", "models/presto", + "models/neo4j", ]; let models = []; let adapters = []; @@ -1527,6 +1532,24 @@ module.exports.generateCode = async function (json_dir, dir_write, options) { ]; break; + case "neo4j": + sections = [ + { dir: "schemas", template: "schemas", fileName: opts.nameLc }, + { dir: "resolvers", template: "resolvers", fileName: opts.nameLc }, + { + dir: "models/neo4j", + template: "models-neo4j", + fileName: opts.nameLc, + }, + { + dir: "validations", + template: "validations", + fileName: opts.nameLc, + }, + { dir: "patches", template: "patches", fileName: opts.nameLc }, + ]; + break; + case "zendro-webservice-adapter": sections = [ { @@ -1631,6 +1654,18 @@ module.exports.generateCode = async function (json_dir, dir_write, options) { { dir: "patches", template: "patches", fileName: opts.adapterName }, ]; break; + + case "neo4j-adapter": + sections = [ + { + dir: "models/adapters", + template: "neo4j-adapter", + fileName: opts.adapterName, + }, + { dir: "patches", template: "patches", fileName: opts.adapterName }, + ]; + break; + default: break; } @@ -1666,7 +1701,7 @@ module.exports.generateCode = async function (json_dir, dir_write, options) { ) { adapters.push(opts.adapterName); } else { - models.push([opts.name , opts.namePl, opts.nameLc]); + models.push([opts.name, opts.namePl, opts.nameLc]); } } //msg diff --git a/lib/generators-aux.js b/lib/generators-aux.js index 65553bac..3f3b5662 100644 --- a/lib/generators-aux.js +++ b/lib/generators-aux.js @@ -18,6 +18,8 @@ exports.getModelDatabase = function (dataModel) { "trino-adapter": "default-trino", presto: "default-presto", "presto-adapter": "default-presto", + neo4j: "default-neo4j", + "neo4j-adapter": "default-neo4j", }; const storageType = dataModel.storageType.toLowerCase(); diff --git a/test/integration_test_misc/data_models_storage_config2.json b/test/integration_test_misc/data_models_storage_config2.json index 23a752b6..4d891137 100644 --- a/test/integration_test_misc/data_models_storage_config2.json +++ b/test/integration_test_misc/data_models_storage_config2.json @@ -20,5 +20,13 @@ "schema":"public", "presto_host": "gql_presto", "presto_port": "8080" + }, + "default-neo4j": { + "storageType": "neo4j", + "username": "neo4j", + "password": "sciencedb", + "database": "neo4j", + "host": "gql_neo4j", + "port": "7687" } } \ No newline at end of file diff --git a/test/integration_test_misc/docker-compose-test.yml b/test/integration_test_misc/docker-compose-test.yml index 1c7809ce..5e38572c 100644 --- a/test/integration_test_misc/docker-compose-test.yml +++ b/test/integration_test_misc/docker-compose-test.yml @@ -58,6 +58,8 @@ services: depends_on: - gql_postgres1 - gql_mongodb1 + - gql_cassandra1 + - gql_minio1 build: context: . dockerfile: Dockerfile.graphql_server @@ -139,10 +141,27 @@ services: networks: - instance2 + gql_neo4j: + image: neo4j + container_name: neo4j1 + user: ${UID_GID} + ports: + - 7474:7474 + - 7687:7687 + volumes: + - ./import:/var/lib/neo4j/import + environment: + NEO4J_AUTH: neo4j/sciencedb + networks: + - instance2 + gql_science_db_graphql_server2: container_name: server2 depends_on: - gql_postgres2 + - gql_presto + - gql_trino + - gql_neo4j build: context: . dockerfile: Dockerfile.graphql_server diff --git a/test/integration_test_misc/import/movie.csv b/test/integration_test_misc/import/movie.csv new file mode 100644 index 00000000..6391ccb5 --- /dev/null +++ b/test/integration_test_misc/import/movie.csv @@ -0,0 +1,7 @@ +movie_id,release,runtime,box_office,is_adult,genres,votes +m1,2008-12-03T10:15:30Z,130,17845632.32,true,action;thriller,50;200;140;1200;150 +m2,2018-12-03T10:15:30Z,110,15645632.32,true,comedy,1;2;14;1200;15000 +m3,2017-12-03T10:15:30Z,120,12345632.32,false,crime;horror,10;21;40;1000;10000 +m4,2018-12-03T10:15:30Z,120,15645632.32,false,crime;horror,1;2;14;1000;15000 +m5,2002-12-03T10:15:30Z,100,145632.32,false,action;mystery,5;20;150;1300;1500 +m6,2021-12-03T10:15:30Z,109,175632.32,true,wuxia;mystery,2;50;140;800;14000 diff --git a/test/integration_test_misc/integration_test_models_instance2/actor.json b/test/integration_test_misc/integration_test_models_instance2/actor.json new file mode 100644 index 00000000..ab42dfae --- /dev/null +++ b/test/integration_test_misc/integration_test_models_instance2/actor.json @@ -0,0 +1,27 @@ +{ + "model" : "actor", + "storageType" : "neo4j", + "attributes" : { + "actor_id": "String", + "actor_name": "String", + "movie_ids": "[String]" + }, + + "associations":{ + "movies":{ + "type": "to_many", + "reverseAssociationType": "to_many", + "target": "movie", + "targetKey": "actor_ids", + "sourceKey": "movie_ids", + "keyIn": "actor", + "targetStorageType": "neo4j" + } + }, + + "internalId": "actor_id", + "id":{ + "name": "actor_id", + "type": "String" + } +} diff --git a/test/integration_test_misc/integration_test_models_instance2/director.json b/test/integration_test_misc/integration_test_models_instance2/director.json new file mode 100644 index 00000000..c5a1d2e8 --- /dev/null +++ b/test/integration_test_misc/integration_test_models_instance2/director.json @@ -0,0 +1,24 @@ +{ + "model": "director", + "storageType": "neo4j", + "attributes": { + "director_id": "String", + "director_name": "String", + "nationality": "String" + }, + "associations": { + "movies": { + "type": "to_many", + "target": "movie", + "targetKey": "director_id", + "keyIn": "movie", + "targetStorageType": "neo4j", + "label": "movie_id" + } + }, + "internalId": "director_id", + "id": { + "name": "director_id", + "type": "String" + } +} \ No newline at end of file diff --git a/test/integration_test_misc/integration_test_models_instance2/dist_director.json b/test/integration_test_misc/integration_test_models_instance2/dist_director.json new file mode 100644 index 00000000..8654b523 --- /dev/null +++ b/test/integration_test_misc/integration_test_models_instance2/dist_director.json @@ -0,0 +1,20 @@ +{ + "model": "dist_director", + "storageType" : "distributed-data-model", + "registry": ["dist_director_instance1"], + "attributes": { + "director_id": "String", + "director_name": "String", + "nationality": "String" + }, + "associations": { + "dist_movies": { + "type": "to_many", + "target": "dist_movie", + "targetKey": "director_id", + "keyIn": "dist_movie", + "targetStorageType": "distributed-data-model" + } + }, + "internalId": "director_id" +} \ No newline at end of file diff --git a/test/integration_test_misc/integration_test_models_instance2/dist_director_instance1.json b/test/integration_test_misc/integration_test_models_instance2/dist_director_instance1.json new file mode 100644 index 00000000..776f86bd --- /dev/null +++ b/test/integration_test_misc/integration_test_models_instance2/dist_director_instance1.json @@ -0,0 +1,22 @@ +{ + "model": "dist_director", + "storageType": "neo4j-adapter", + "adapterName": "dist_director_instance1", + "regex": "instance1", + "attributes": { + "director_id": "String", + "director_name": "String", + "nationality": "String" + }, + "associations": { + "dist_movies": { + "type": "to_many", + "target": "dist_movie", + "targetKey": "director_id", + "keyIn": "dist_movie", + "targetStorageType": "distributed-data-model" + } + }, + "internalId": "director_id" +} + \ No newline at end of file diff --git a/test/integration_test_misc/integration_test_models_instance2/dist_movie.json b/test/integration_test_misc/integration_test_models_instance2/dist_movie.json new file mode 100644 index 00000000..3d9a93fa --- /dev/null +++ b/test/integration_test_misc/integration_test_models_instance2/dist_movie.json @@ -0,0 +1,27 @@ +{ + "model": "dist_movie", + "storageType" : "distributed-data-model", + "registry": ["dist_movie_instance1"], + "attributes": { + "movie_id": "String", + "release": "DateTime", + "runtime": "Int", + "box_office": "Float", + "is_adult": "Boolean", + "genres": "[String]", + "votes": "[Int]", + "director_id": "String" + }, + + "associations": { + "dist_director": { + "type": "to_one", + "target": "dist_director", + "targetKey": "director_id", + "keyIn" : "dist_movie", + "targetStorageType": "distributed-data-model" + } + }, + + "internalId" : "movie_id" +} \ No newline at end of file diff --git a/test/integration_test_misc/integration_test_models_instance2/dist_movie_instance1.json b/test/integration_test_misc/integration_test_models_instance2/dist_movie_instance1.json new file mode 100644 index 00000000..5816349a --- /dev/null +++ b/test/integration_test_misc/integration_test_models_instance2/dist_movie_instance1.json @@ -0,0 +1,28 @@ +{ + "model": "dist_movie", + "storageType": "neo4j-adapter", + "adapterName": "dist_movie_instance1", + "regex": "instance1", + "attributes": { + "movie_id": "String", + "release": "DateTime", + "runtime": "Int", + "box_office": "Float", + "is_adult": "Boolean", + "genres": "[String]", + "votes": "[Int]", + "director_id": "String" + }, + "associations": { + "dist_director": { + "type": "to_one", + "target": "dist_director", + "targetKey": "director_id", + "keyIn": "dist_movie", + "targetStorageType": "distributed-data-model" + } + }, + + "internalId": "movie_id" +} + \ No newline at end of file diff --git a/test/integration_test_misc/integration_test_models_instance2/movie.json b/test/integration_test_misc/integration_test_models_instance2/movie.json new file mode 100644 index 00000000..a06dca5d --- /dev/null +++ b/test/integration_test_misc/integration_test_models_instance2/movie.json @@ -0,0 +1,42 @@ +{ + "model" : "movie", + "storageType" : "neo4j", + "attributes" : { + "movie_id": "String", + "release":"DateTime", + "runtime": "Int", + "box_office": "Float", + "is_adult": "Boolean", + "genres": "[String]", + "votes":"[Int]", + "director_id":"String", + "actor_ids": "[String]" + }, + "associations": { + "director": { + "type": "to_one", + "target": "director", + "targetKey": "director_id", + "keyIn": "movie", + "targetStorageType": "neo4j", + "label": "director_name" + }, + "actor":{ + "type": "to_many", + "reverseAssociationType": "to_many", + "target": "actor", + "targetKey": "movie_ids", + "sourceKey": "actor_ids", + "keyIn": "movie", + "targetStorageType": "neo4j" + }, + "unique_review":{ + "type" : "to_one", + "target" : "review", + "targetKey" : "movie_id", + "keyIn": "tracker", + "targetStorageType" : "neo4j" + } + }, + "internalId": "movie_id" +} diff --git a/test/integration_test_misc/integration_test_models_instance2/review.json b/test/integration_test_misc/integration_test_models_instance2/review.json new file mode 100644 index 00000000..2c5006da --- /dev/null +++ b/test/integration_test_misc/integration_test_models_instance2/review.json @@ -0,0 +1,23 @@ +{ + "model" : "review", + "storageType" : "neo4j", + "attributes" : { + "review_id": "String", + "movie_id": "String", + "rating": "Float" + }, + "associations": { + "unique_movie": { + "type" : "to_one", + "target" : "movie", + "targetKey" : "movie_id", + "keyIn": "review", + "targetStorageType" : "neo4j" + } + }, + "internalId": "review_id", + "id": { + "name": "review_id", + "type": "String" + } +} \ No newline at end of file diff --git a/test/mocha_integration.test.js b/test/mocha_integration.test.js index 956012e7..f139f428 100644 --- a/test/mocha_integration.test.js +++ b/test/mocha_integration.test.js @@ -383,8 +383,8 @@ describe('Clean GraphQL Server: one new basic function per test ("Individual" mo expect(res.statusCode).to.equal(200); expect(resBody).to.deep.equal({ - data:{t:[{gene:"Gene D"}],i:[{name:"Zazaniza"}]} - }) + data: { t: [{ gene: "Gene D" }], i: [{ name: "Zazaniza" }] }, + }); res = itHelpers.request_graph_ql_post( `{ individuals (search: {field: name, operator: regexp, value: "Zazan[aeiou]za"},pagination:{limit:25}) {name}}` @@ -420,10 +420,10 @@ describe('Clean GraphQL Server: one new basic function per test ("Individual" mo resBody = JSON.parse(res.body.toString("utf8")); expect(res.statusCode).to.equal(200); expect(resBody).to.deep.equal({ - "data":{ - "firstPerson":[{"name":"Zazanaza"}], - "secondPerson":[{"name":"Zazaniza"}] - } + data: { + firstPerson: [{ name: "Zazanaza" }], + secondPerson: [{ name: "Zazaniza" }], + }, }); res = await itHelpers.request_metaquery_post( @@ -436,38 +436,36 @@ describe('Clean GraphQL Server: one new basic function per test ("Individual" mo ); resBody = JSON.parse(res.body.toString("utf8")); expect(res.statusCode).to.equal(200); - - expect(resBody).to.deep.equal( - { - "errors": [ - { - "message": "Cannot query field \"names\" on type \"individual\". Did you mean \"name\"?", - "locations": [ - { - "line": 2, - "column": 114 - } - ] - }, - { - "message": "Cannot query field \"names\" on type \"individual\". Did you mean \"name\"?", - "locations": [ - { - "line": 3, - "column": 116 - } - ] - } - ] - } - ); + expect(resBody).to.deep.equal({ + errors: [ + { + message: + 'Cannot query field "names" on type "individual". Did you mean "name"?', + locations: [ + { + line: 2, + column: 114, + }, + ], + }, + { + message: + 'Cannot query field "names" on type "individual". Did you mean "name"?', + locations: [ + { + line: 3, + column: 116, + }, + ], + }, + ], + }); res = await itHelpers.request_metaquery_post( `{ firstPerson: individuals (search: {field: name, operator: eq, value: "Zazanaza"},pagination:{limit:10}) {name} secondPerson: individuals (search: {field: name, operator: eq, value: "Zazaniza"},pagination:{limit:10}) {name} - }` - , + }`, ".firstPerson", null ); @@ -475,13 +473,12 @@ describe('Clean GraphQL Server: one new basic function per test ("Individual" mo resBody = JSON.parse(res.body.toString("utf8")); expect(res.statusCode).to.equal(200); expect(resBody).to.deep.equal({ - "data": [ + data: [ { - "name": "Zazanaza" - } - ] - } - ); + name: "Zazanaza", + }, + ], + }); res = await itHelpers.request_metaquery_post( `{ @@ -494,16 +491,16 @@ describe('Clean GraphQL Server: one new basic function per test ("Individual" mo resBody = JSON.parse(res.body.toString("utf8")); expect(res.statusCode).to.equal(200); - + expect(resBody).to.deep.equal({ - "data": null, - "errors": [ + data: null, + errors: [ { - "message": "jq: error: syntax error, unexpected INVALID_CHARACTER (Unix shell quoting issues?) at , line 1:\n.~firstPerson \njq: error: try .[\"field\"] instead of .field for unusually named fields at , line 1:\n.~firstPerson\njq: 2 compile errors\n" - } - ] - } - ); + message: + 'jq: error: syntax error, unexpected INVALID_CHARACTER (Unix shell quoting issues?) at , line 1:\n.~firstPerson \njq: error: try .["field"] instead of .field for unusually named fields at , line 1:\n.~firstPerson\njq: 2 compile errors\n', + }, + ], + }); res = await itHelpers.request_metaquery_post( `{ @@ -517,20 +514,19 @@ describe('Clean GraphQL Server: one new basic function per test ("Individual" mo resBody = JSON.parse(res.body.toString("utf8")); expect(res.statusCode).to.equal(200); expect(resBody).to.deep.equal({ - "data": { - "firstPerson": [ + data: { + firstPerson: [ { - "name": "Zazanaza" - } + name: "Zazanaza", + }, ], - "secondPerson": [ + secondPerson: [ { - "name": "Zazaniza" - } - ] - } - } - ); + name: "Zazaniza", + }, + ], + }, + }); res = await itHelpers.request_metaquery_post( `{ @@ -542,14 +538,14 @@ describe('Clean GraphQL Server: one new basic function per test ("Individual" mo ); resBody = JSON.parse(res.body.toString("utf8")); - + expect(res.statusCode).to.equal(200); expect(resBody).to.deep.equal({ - "data": [ + data: [ { - "name": "Zazanaza" - } - ] + name: "Zazanaza", + }, + ], }); res = await itHelpers.request_metaquery_post( @@ -564,11 +560,11 @@ describe('Clean GraphQL Server: one new basic function per test ("Individual" mo resBody = JSON.parse(res.body.toString("utf8")); expect(res.statusCode).to.equal(200); expect(resBody).to.deep.equal({ - "data": [ + data: [ { - "name": "Zazanaza" - } - ] + name: "Zazanaza", + }, + ], }); res = await itHelpers.request_metaquery_post( diff --git a/test/mocha_integration_neo4j.test.js b/test/mocha_integration_neo4j.test.js new file mode 100644 index 00000000..1624eb6e --- /dev/null +++ b/test/mocha_integration_neo4j.test.js @@ -0,0 +1,998 @@ +const { expect } = require("chai"); +const delay = require("delay"); +const path = require("path"); +const itHelpers = require("./integration_test_misc/integration_test_helpers"); + +describe("Neo4j - Basic CRUD Operations", () => { + after(async () => { + // Delete all movies + let res = itHelpers.request_graph_ql_post_instance2( + "{ movies(pagination:{limit:25}) {movie_id} }" + ); + let movies = JSON.parse(res.body.toString("utf8")).data.movies; + + for (let i = 0; i < movies.length; i++) { + res = itHelpers.request_graph_ql_post_instance2( + `mutation { deleteMovie (movie_id: "${movies[i].movie_id}") }` + ); + expect(res.statusCode).to.equal(200); + } + res = itHelpers.request_graph_ql_post_instance2("{ countMovies }"); + let cnt = JSON.parse(res.body.toString("utf8")).data.countMovies; + expect(cnt).to.equal(0); + }); + + it("01. Movie: empty table", () => { + let res = itHelpers.request_graph_ql_post_instance2("{ countMovies }"); + let resBody = JSON.parse(res.body.toString("utf8")); + + expect(res.statusCode).to.equal(200); + expect(resBody.data.countMovies).equal(0); + }); + + it("02. Movie: add", async () => { + // movie_id,release,runtime,box_office,is_adult,genres,votes + // m1,2008-12-03T10:15:30Z,130,17845632.32,true,action;thriller,50;200;140;1200;150 + let res = itHelpers.request_graph_ql_post_instance2( + `mutation{ + addMovie(movie_id:"m0", release:"1998-12-03T10:15:30Z", runtime:110, box_office:13145632.32, + is_adult:false, genres:["action","thriller"], votes: [50,200,140,1200,150]) + { + movie_id + genres + votes + } + }` + ); + + expect(res.statusCode).to.equal(200); + + res = itHelpers.request_graph_ql_post_instance2("{ countMovies }"); + let cnt = JSON.parse(res.body.toString("utf8")).data.countMovies; + expect(cnt).to.equal(1); + }); + + it("03. Movie: update", () => { + let res = itHelpers.request_graph_ql_post_instance2( + '{movies(search:{field:is_adult operator:eq value:"false"}, pagination:{limit:25}){movie_id}}' + ); + let resBody = JSON.parse(res.body.toString("utf8")); + let movie = resBody.data.movies[0].movie_id; + + res = itHelpers.request_graph_ql_post_instance2( + `mutation { updateMovie(movie_id: "${movie}", runtime:111) { + movie_id + runtime + } + }` + ); + resBody = JSON.parse(res.body.toString("utf8")); + + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + updateMovie: { + movie_id: `${movie}`, + runtime: 111, + }, + }, + }); + }); + + it("04. Movie: read", () => { + let res = itHelpers.request_graph_ql_post_instance2( + '{movies(search:{field:release, operator:eq, value:"1998-12-03T10:15:30.000Z"}, pagination:{limit:25}){movie_id}}' + ); + let resBody = JSON.parse(res.body.toString("utf8")); + let movie = resBody.data.movies[0].movie_id; + + res = itHelpers.request_graph_ql_post_instance2( + `{ + readOneMovie(movie_id : "${movie}") { + movie_id + release + runtime + box_office + is_adult + genres + votes + } + }` + ); + resBody = JSON.parse(res.body.toString("utf8")); + + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + readOneMovie: { + movie_id: "m0", + release: "1998-12-03T10:15:30.000Z", + runtime: 111, + box_office: 13145632.32, + is_adult: false, + genres: ["action", "thriller"], + votes: [50, 200, 140, 1200, 150], + }, + }, + }); + }); + + it("05. Movie: search with regex", () => { + let res = itHelpers.request_graph_ql_post_instance2( + '{movies(search:{field:movie_id, value:"m.*", operator:regexp},pagination:{limit:25}) {movie_id}}' + ); + let resBody = JSON.parse(res.body.toString("utf8")); + + expect(res.statusCode).to.equal(200); + expect(resBody.data.movies.length).equal(1); + }); + + it("06. Movie: delete", async () => { + let res = itHelpers.request_graph_ql_post_instance2( + "{ movies(pagination:{limit:25}) {movie_id} }" + ); + let movies = JSON.parse(res.body.toString("utf8")).data.movies; + + for (let i = 0; i < movies.length; i++) { + res = itHelpers.request_graph_ql_post_instance2( + `mutation { deleteMovie (movie_id: "${movies[i].movie_id}") }` + ); + expect(res.statusCode).to.equal(200); + } + + res = itHelpers.request_graph_ql_post_instance2("{ countMovies }"); + let cnt = JSON.parse(res.body.toString("utf8")).data.countMovies; + expect(cnt).to.equal(0); + }); + + it("07. Movie: CSV bulkUpload", async () => { + let res = itHelpers.request_graph_ql_post_instance2("{ countMovies }"); + let cnt1 = JSON.parse(res.body.toString("utf8")).data.countMovies; + + res = itHelpers.request_graph_ql_post_instance2( + "mutation {bulkAddMovieCsv}" + ); + + expect(JSON.parse(res.body.toString("utf8")).data.bulkAddMovieCsv).equal( + "Successfully upload file" + ); + await delay(500); + + res = itHelpers.request_graph_ql_post_instance2("{ countMovies }"); + let cnt2 = JSON.parse(res.body.toString("utf8")).data.countMovies; + expect(cnt2 - cnt1).to.equal(6); + }); + + it("08. Movie: paginate", () => { + let res = itHelpers.request_graph_ql_post_instance2( + "{movies(pagination:{limit:1}) {movie_id}}" + ); + let resBody = JSON.parse(res.body.toString("utf8")); + + expect(res.statusCode).to.equal(200); + expect(resBody.data.movies.length).equal(1); + + res = itHelpers.request_graph_ql_post_instance2( + `{ + moviesConnection(pagination:{first:10}) { + edges{ + cursor + node{ + movie_id + } + } + } + }` + ); + resBody = JSON.parse(res.body.toString("utf8")); + let edges = resBody.data.moviesConnection.edges; + let idArray = edges.map((edge) => edge.node.movie_id); + let cursorArray = edges.map((edge) => edge.cursor); + res = itHelpers.request_graph_ql_post_instance2( + `{ + moviesConnection(pagination:{first: 2, after: "${cursorArray[1]}"}) { + movies{ + movie_id + } + edges{ + cursor + node{ + movie_id + } + } + pageInfo{ + endCursor + hasNextPage + } + } + }` + ); + resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + moviesConnection: { + movies: [ + { + movie_id: "m3", + }, + { + movie_id: "m4", + }, + ], + edges: [ + { + cursor: cursorArray[2], + node: { + movie_id: idArray[2], + }, + }, + { + cursor: cursorArray[3], + node: { + movie_id: idArray[3], + }, + }, + ], + pageInfo: { + endCursor: cursorArray[3], + hasNextPage: true, + }, + }, + }, + }); + }); + + it("09. Movie: sort", () => { + let res = itHelpers.request_graph_ql_post_instance2( + `{ + movies(pagination: {limit:2}, order: [{field: runtime, order: DESC}]) { + movie_id + runtime + } + }` + ); + let resBody = JSON.parse(res.body.toString("utf8")); + + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + movies: [ + { movie_id: "m1", runtime: 130 }, + { movie_id: "m3", runtime: 120 }, + ], + }, + }); + }); + + it("10. Movie: get the table template", () => { + let res = itHelpers.request_graph_ql_post_instance2( + `{csvTableTemplateMovie}` + ); + let resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + csvTableTemplateMovie: [ + "movie_id,release,runtime,box_office,is_adult,genres,votes,director_id,actor_ids", + "String,DateTime,Int,Float,Boolean,[String],[Int],String,[String]", + ], + }, + }); + }); +}); + +describe("Neo4j - Association", () => { + // set up the environment + before(async () => { + let res = itHelpers.request_graph_ql_post_instance2( + "mutation {bulkAddMovieCsv}" + ); + + expect(JSON.parse(res.body.toString("utf8")).data.bulkAddMovieCsv).equal( + "Successfully upload file" + ); + await delay(500); + }); + + // clean up records + after(async () => { + // Delete all movies + let res = itHelpers.request_graph_ql_post_instance2( + "{ movies(pagination:{limit:25}) {movie_id} }" + ); + let movies = JSON.parse(res.body.toString("utf8")).data.movies; + + for (let i = 0; i < movies.length; i++) { + res = itHelpers.request_graph_ql_post_instance2( + `mutation { deleteMovie (movie_id: "${movies[i].movie_id}") }` + ); + expect(res.statusCode).to.equal(200); + } + + res = itHelpers.request_graph_ql_post_instance2("{ countMovies }"); + let cnt = JSON.parse(res.body.toString("utf8")).data.countMovies; + expect(cnt).to.equal(0); + + // Delete all directors + res = itHelpers.request_graph_ql_post_instance2( + "{ directors(pagination:{limit:25}) {director_id} }" + ); + let directors = JSON.parse(res.body.toString("utf8")).data.directors; + + for (let i = 0; i < directors.length; i++) { + res = itHelpers.request_graph_ql_post_instance2( + `mutation { deleteDirector (director_id: "${directors[i].director_id}") }` + ); + expect(res.statusCode).to.equal(200); + } + + res = itHelpers.request_graph_ql_post_instance2("{ countDirectors }"); + cnt = JSON.parse(res.body.toString("utf8")).data.countDirectors; + expect(cnt).to.equal(0); + + // Delete all kinds of actor + res = itHelpers.request_graph_ql_post_instance2( + "{ actors(pagination:{limit:25}) {actor_id} }" + ); + let actor = JSON.parse(res.body.toString("utf8")).data.actors; + + for (let i = 0; i < actor.length; i++) { + res = itHelpers.request_graph_ql_post_instance2( + `mutation { deleteActor (actor_id: "${actor[i].actor_id}") }` + ); + expect(res.statusCode).to.equal(200); + } + + res = itHelpers.request_graph_ql_post_instance2("{ countActors }"); + cnt = JSON.parse(res.body.toString("utf8")).data.countActors; + expect(cnt).to.equal(0); + + // Delete all reviews + res = itHelpers.request_graph_ql_post_instance2( + "{ reviews(pagination:{limit:25}) {review_id} }" + ); + let review = JSON.parse(res.body.toString("utf8")).data.reviews; + + for (let i = 0; i < review.length; i++) { + res = itHelpers.request_graph_ql_post_instance2( + `mutation { deleteReview (review_id: "${review[i].review_id}") }` + ); + expect(res.statusCode).to.equal(200); + } + + res = itHelpers.request_graph_ql_post_instance2("{ countReviews }"); + cnt = JSON.parse(res.body.toString("utf8")).data.countReviews; + expect(cnt).to.equal(0); + }); + + it("01. Movie : Director (n:1) - add movies to director", () => { + let res = itHelpers.request_graph_ql_post_instance2( + `mutation{ + addDirector( director_id: "d1", director_name: "Chloé Zhao", addMovies: ["m1", "m2"] ){ + director_name + moviesFilter(pagination:{limit:10}){ + movie_id + genres + } + } + }` + ); + let resBody = JSON.parse(res.body.toString("utf8")); + + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + addDirector: { + moviesFilter: [ + { + movie_id: "m1", + genres: ["action", "thriller"], + }, + { + movie_id: "m2", + genres: ["comedy"], + }, + ], + director_name: "Chloé Zhao", + }, + }, + }); + }); + it("02. Movie : Director (n:1) - read one associated movie", () => { + let res = itHelpers.request_graph_ql_post_instance2( + `{ + readOneMovie(movie_id: "m1"){ + movie_id + director{ + director_name + } + } + }` + ); + let resBody = JSON.parse(res.body.toString("utf8")); + + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + readOneMovie: { + director: { + director_name: "Chloé Zhao", + }, + movie_id: "m1", + }, + }, + }); + }); + + it("03. Movie : Director (n:1) - deleting the director record with associations fails", () => { + let res = itHelpers.request_graph_ql_post_instance2( + `mutation { deleteDirector (director_id: "d1") }` + ); + let resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(500); + expect(resBody).to.deep.equal({ + errors: [ + { + message: `director with director_id d1 has associated records and is NOT valid for deletion. Please clean up before you delete.`, + locations: [ + { + column: 12, + line: 1, + }, + ], + path: ["deleteDirector"], + }, + ], + data: null, + }); + }); + + it("04. Movie : Director (n:1) - delete the associations in the director record", () => { + let res = itHelpers.request_graph_ql_post_instance2( + `mutation{updateDirector(director_id: "d1", removeMovies: ["m1", "m2"]) { + director_name + moviesFilter(pagination:{limit:10}){ + movie_id + } + moviesConnection(pagination:{first:5}){ + movies{ + movie_id + } + } + } + }` + ); + + resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + updateDirector: { + moviesFilter: [], + director_name: "Chloé Zhao", + moviesConnection: { + movies: [], + }, + }, + }, + }); + }); + + it("05. Movie : Actor (n:n) - add movies to actor", () => { + const actors = ["Yokohama Ryusei", "Minami Hamabe"]; + for (let i = 1; i < 3; i++) { + let res = itHelpers.request_graph_ql_post_instance2( + `mutation{ + addActor(actor_id:"a${i}", actor_name:"${actors[i - 1]}", + addMovies:["m3","m4"]){ + actor_id + movie_ids + } + }` + ); + let resBody = JSON.parse(res.body.toString("utf8")); + + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + addActor: { + actor_id: `a${i}`, + movie_ids: ["m3", "m4"], + }, + }, + }); + } + }); + + it("06. Movie : Actor (n:n) - read one associated movie", () => { + let res = itHelpers.request_graph_ql_post_instance2(` + { + readOneMovie(movie_id: "m3"){ + movie_id + actor_ids + } + }`); + let resBody = JSON.parse(res.body.toString("utf8")); + + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + readOneMovie: { + movie_id: "m3", + actor_ids: ["a1", "a2"], + }, + }, + }); + }); + + it("07. Movie : Actor (n:n) - delete the associations in the actor records", () => { + for (let i = 1; i < 3; i++) { + let res = itHelpers.request_graph_ql_post_instance2( + `mutation{ + updateActor(actor_id:"a${i}", removeMovies:["m3","m4"]){ + actor_id + movie_ids + } + }` + ); + resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + updateActor: { + actor_id: `a${i}`, + movie_ids: [], + }, + }, + }); + } + }); + + it("08. Movie : Review (1:1) - add movie to review", () => { + let res = itHelpers.request_graph_ql_post_instance2( + `mutation{ + addReview(review_id:"r1", rating:4.9, addUnique_movie:"m5"){ + review_id + movie_id + } + }` + ); + let resBody = JSON.parse(res.body.toString("utf8")); + + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + addReview: { + review_id: "r1", + movie_id: "m5", + }, + }, + }); + }); + + it("09. Movie : Review (1:1) - read one associated movie", () => { + let res = itHelpers.request_graph_ql_post_instance2(` + { + readOneMovie(movie_id: "m5"){ + movie_id + unique_review { + review_id + rating + } + } + }`); + let resBody = JSON.parse(res.body.toString("utf8")); + + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + readOneMovie: { + movie_id: "m5", + unique_review: { + review_id: "r1", + rating: 4.9, + }, + }, + }, + }); + }); + + it("10. Movie : Review (1:1) - violate the unique rule", () => { + itHelpers.request_graph_ql_post_instance2( + `mutation{ + addReview(review_id:"r2", rating:3.5, addUnique_movie:"m5"){ + review_id + movie_id + } + }` + ); + res = itHelpers.request_graph_ql_post_instance2( + `{ + readOneMovie(movie_id: "m5"){ + movie_id + unique_review { + review_id + } + } + }` + ); + resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + errors: [ + { + message: + 'Not unique "to_one" association Error: Found > 1 reviews matching movie with movie_id m5. Consider making this a "to_many" association, or using unique constraints, or moving the foreign key into the movie model. Returning first review.', + locations: "", + }, + ], + data: { + readOneMovie: { + movie_id: "m5", + unique_review: { + review_id: "r1", + }, + }, + }, + }); + }); + + it("11. Movie : Review (1:1) - delete the associations in the review record", () => { + for (let i = 1; i < 3; i++) { + let res = itHelpers.request_graph_ql_post_instance2( + `mutation{ + updateReview(review_id:"r${i}", removeUnique_movie:"m5"){ + review_id + movie_id + } + }` + ); + resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + updateReview: { + review_id: `r${i}`, + movie_id: null, + }, + }, + }); + } + }); +}); + +describe("Neo4j - Distributed Data Models", () => { + after(async () => { + // Delete all movies + let res = itHelpers.request_graph_ql_post_instance2( + "{ dist_moviesConnection(pagination:{first:10}) {edges {node {movie_id}}}}" + ); + let edges = JSON.parse(res.body.toString("utf8")).data.dist_moviesConnection + .edges; + for (let edge of edges) { + res = itHelpers.request_graph_ql_post_instance2( + `mutation { deleteDist_movie (movie_id: "${edge.node.movie_id}") }` + ); + expect(res.statusCode).to.equal(200); + } + res = itHelpers.request_graph_ql_post_instance2("{ countDist_movies }"); + let cnt = JSON.parse(res.body.toString("utf8")).data.countDist_movies; + expect(cnt).to.equal(0); + // Delete all directors + res = itHelpers.request_graph_ql_post_instance2( + "{ dist_directorsConnection(pagination:{first:10}) {edges {node {director_id}}}}" + ); + edges = JSON.parse(res.body.toString("utf8")).data.dist_directorsConnection + .edges; + for (let edge of edges) { + res = itHelpers.request_graph_ql_post_instance2( + `mutation { deleteDist_director (director_id: "${edge.node.director_id}") }` + ); + expect(res.statusCode).to.equal(200); + } + res = itHelpers.request_graph_ql_post_instance2("{ countDist_directors }"); + cnt = JSON.parse(res.body.toString("utf8")).data.countDist_directors; + expect(cnt).to.equal(0); + }); + + it("01. Movie DDM: create a director and 3 movies", () => { + let res = itHelpers.request_graph_ql_post_instance2( + `mutation { + addDist_director(director_id: "instance1-01", director_name: "Chloé Zhao") { + director_id + director_name + } + }` + ); + let resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + addDist_director: { + director_id: "instance1-01", + director_name: "Chloé Zhao", + }, + }, + }); + const runtime = [110, 145, 120]; + for (let i = 0; i < runtime.length; i++) { + res = itHelpers.request_graph_ql_post_instance2( + `mutation { + addDist_movie(movie_id: "instance1-0${i + 2}", + runtime: ${runtime[i]}) + { + movie_id + runtime + } + } + ` + ); + resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + addDist_movie: { + movie_id: `instance1-0${i + 2}`, + runtime: runtime[i], + }, + }, + }); + } + }); + it("02. Movie DDM: update the director to associate with movies", () => { + let res = itHelpers.request_graph_ql_post_instance2( + `mutation { + updateDist_director(director_id: "instance1-01", addDist_movies: ["instance1-02", "instance1-03"]) { + director_name + countFilteredDist_movies + dist_moviesConnection(pagination: {first: 5}) { + edges { + node { + runtime + } + } + dist_movies{ + movie_id + } + } + } + } + ` + ); + let resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + updateDist_director: { + director_name: "Chloé Zhao", + countFilteredDist_movies: 2, + dist_moviesConnection: { + edges: [ + { + node: { + runtime: 110, + }, + }, + { + node: { + runtime: 145, + }, + }, + ], + dist_movies: [ + { movie_id: "instance1-02" }, + { movie_id: "instance1-03" }, + ], + }, + }, + }, + }); + }); + it("03. Movie DDM: read all", () => { + let res = itHelpers.request_graph_ql_post_instance2( + `{ + dist_directorsConnection(pagination: {first: 25}) { + edges { + node { + director_id + countFilteredDist_movies + } + } + } + } + ` + ); + let resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + dist_directorsConnection: { + edges: [ + { + node: { + director_id: "instance1-01", + countFilteredDist_movies: 2, + }, + }, + ], + }, + }, + }); + }); + it("04. Movie DDM: search, sort and pagination", () => { + res = itHelpers.request_graph_ql_post_instance2( + `{ + dist_moviesConnection(search: {field: movie_id, value: "instance.*", operator: regexp}, pagination: {first: 5}) { + edges { + node { + movie_id + runtime + } + } + } + } + ` + ); + resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + dist_moviesConnection: { + edges: [ + { + node: { + movie_id: "instance1-02", + runtime: 110, + }, + }, + { + node: { + movie_id: "instance1-03", + runtime: 145, + }, + }, + { + node: { + movie_id: "instance1-04", + runtime: 120, + }, + }, + ], + }, + }, + }); + // The same search, but order by name descending + res = itHelpers.request_graph_ql_post_instance2( + `{ + dist_moviesConnection(search: {field: movie_id, value: "instance.*", operator: regexp}, + order:{field:runtime order:DESC}, pagination: {first: 5}) { + edges { + node { + movie_id + runtime + } + } + } + }` + ); + resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + dist_moviesConnection: { + edges: [ + { + node: { + movie_id: "instance1-03", + runtime: 145, + }, + }, + { + node: { + movie_id: "instance1-04", + runtime: 120, + }, + }, + { + node: { + movie_id: "instance1-02", + runtime: 110, + }, + }, + ], + }, + }, + }); + res = itHelpers.request_graph_ql_post_instance2( + `{ + dist_moviesConnection(pagination: {first: 5, + after:"eyJtb3ZpZV9pZCI6Imluc3RhbmNlMS0wMiIsInJ1bnRpbWUiOjExMCwiZGlyZWN0b3JfaWQiOiJpbnN0YW5jZTEtMDEifQ==" + }){ + edges { + node { + movie_id + runtime + } + cursor + } + pageInfo { + startCursor + endCursor + hasNextPage + hasPreviousPage + } + } + } + ` + ); + resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + dist_moviesConnection: { + edges: [ + { + cursor: + "eyJtb3ZpZV9pZCI6Imluc3RhbmNlMS0wMyIsInJ1bnRpbWUiOjE0NSwiZGlyZWN0b3JfaWQiOiJpbnN0YW5jZTEtMDEifQ==", + node: { + movie_id: "instance1-03", + runtime: 145, + }, + }, + { + cursor: + "eyJtb3ZpZV9pZCI6Imluc3RhbmNlMS0wNCIsInJ1bnRpbWUiOjEyMH0=", + node: { + movie_id: "instance1-04", + runtime: 120, + }, + }, + ], + pageInfo: { + startCursor: + "eyJtb3ZpZV9pZCI6Imluc3RhbmNlMS0wMyIsInJ1bnRpbWUiOjE0NSwiZGlyZWN0b3JfaWQiOiJpbnN0YW5jZTEtMDEifQ==", + endCursor: + "eyJtb3ZpZV9pZCI6Imluc3RhbmNlMS0wNCIsInJ1bnRpbWUiOjEyMH0=", + hasNextPage: false, + hasPreviousPage: false, + }, + }, + }, + }); + }); + it("05. Movie DDM: update the director to remove associations", () => { + let res = itHelpers.request_graph_ql_post_instance2( + `mutation { + updateDist_director(director_id:"instance1-01" removeDist_movies:["instance1-02", "instance1-03"]) { + director_name + countFilteredDist_movies + dist_moviesConnection(pagination:{first:5}){ + edges { + node { + runtime + } + } + dist_movies{ + movie_id + } + } + } + }` + ); + let resBody = JSON.parse(res.body.toString("utf8")); + expect(res.statusCode).to.equal(200); + expect(resBody).to.deep.equal({ + data: { + updateDist_director: { + director_name: "Chloé Zhao", + countFilteredDist_movies: 0, + dist_moviesConnection: { + edges: [], + dist_movies: [], + }, + }, + }, + }); + }); +}); diff --git a/test/mocha_unit.test.js b/test/mocha_unit.test.js index 7cb368ca..c9bd4299 100644 --- a/test/mocha_unit.test.js +++ b/test/mocha_unit.test.js @@ -12,6 +12,7 @@ const models_cassandra = require("./unit_test_misc/data_models_cassandra"); const models_mongodb = require("./unit_test_misc/data_models_mongodb"); const models_amazonS3 = require("./unit_test_misc/data_models_amazonS3"); const models_trino = require("./unit_test_misc/data_models_trino"); +const models_neo4j = require("./unit_test_misc/data_models_neo4j"); const requireFromString = require("require-from-string"); const helpers = require("./unit_test_misc/helpers/reporting_helpers"); const { test } = require("mocha"); @@ -66,10 +67,8 @@ describe("Lower-case models", function () { ); expect(g_model, "Incorrect model").to.have.string(test_model_attributes); - let test_model_associations = data_test.individual_model_associations.replace( - /\s/g, - "" - ); + let test_model_associations = + data_test.individual_model_associations.replace(/\s/g, ""); expect(g_model, "Incorrect model").to.have.string(test_model_associations); }); }); @@ -988,10 +987,11 @@ describe("Cursor based pagination", function () { let opts = funks.getOptions(models_zendro.person); let generated_model = await funks.generateJs("create-models-zendro", opts); let g_model = generated_model.replace(/\s/g, ""); - let test_model = data_test.many_to_many_association_connection_zendro_server.replace( - /\s/g, - "" - ); + let test_model = + data_test.many_to_many_association_connection_zendro_server.replace( + /\s/g, + "" + ); expect(g_model, "No method found").to.have.string(test_model); }); }); @@ -1766,10 +1766,8 @@ describe("Refactor associations - add / update SQL models", function () { let opts = funks.getOptions(models_refactoring.accession); let generated_resolver = await funks.generateJs("create-resolvers", opts); let g_resolver = generated_resolver.replace(/\s/g, ""); - let test_resolver = data_test.add_assoc_to_one_fieldMutation_resolver.replace( - /\s/g, - "" - ); + let test_resolver = + data_test.add_assoc_to_one_fieldMutation_resolver.replace(/\s/g, ""); expect(g_resolver).to.have.string(test_resolver); }); @@ -1777,10 +1775,8 @@ describe("Refactor associations - add / update SQL models", function () { let opts = funks.getOptions(models_refactoring.accession); let generated_resolver = await funks.generateJs("create-resolvers", opts); let g_resolver = generated_resolver.replace(/\s/g, ""); - let test_resolver = data_test.remove_assoc_to_one_fieldMutation_resolver.replace( - /\s/g, - "" - ); + let test_resolver = + data_test.remove_assoc_to_one_fieldMutation_resolver.replace(/\s/g, ""); expect(g_resolver).to.have.string(test_resolver); }); @@ -1788,10 +1784,11 @@ describe("Refactor associations - add / update SQL models", function () { let opts = funks.getOptions(models.researcher); let generated_resolvers = await funks.generateJs("create-resolvers", opts); let g_resolvers = generated_resolvers.replace(/\s/g, ""); - let test_resolver = data_test.add_assoc_to_one_fieldMutation_resolver_fK_in_target.replace( - /\s/g, - "" - ); + let test_resolver = + data_test.add_assoc_to_one_fieldMutation_resolver_fK_in_target.replace( + /\s/g, + "" + ); expect(g_resolvers).to.have.string(test_resolver); }); @@ -1799,10 +1796,11 @@ describe("Refactor associations - add / update SQL models", function () { let opts = funks.getOptions(models.researcher); let generated_resolvers = await funks.generateJs("create-resolvers", opts); let g_resolvers = generated_resolvers.replace(/\s/g, ""); - let test_resolver = data_test.remove_assoc_to_one_fieldMutation_resolver_fK_in_target.replace( - /\s/g, - "" - ); + let test_resolver = + data_test.remove_assoc_to_one_fieldMutation_resolver_fK_in_target.replace( + /\s/g, + "" + ); expect(g_resolvers).to.have.string(test_resolver); }); @@ -1810,10 +1808,8 @@ describe("Refactor associations - add / update SQL models", function () { let opts = funks.getOptions(models_refactoring.accession); let generated_resolver = await funks.generateJs("create-resolvers", opts); let g_resolver = generated_resolver.replace(/\s/g, ""); - let test_resolver = data_test.add_assoc_to_many_fieldMutation_resolver.replace( - /\s/g, - "" - ); + let test_resolver = + data_test.add_assoc_to_many_fieldMutation_resolver.replace(/\s/g, ""); expect(g_resolver).to.have.string(test_resolver); }); @@ -1821,10 +1817,8 @@ describe("Refactor associations - add / update SQL models", function () { let opts = funks.getOptions(models_refactoring.accession); let generated_resolver = await funks.generateJs("create-resolvers", opts); let g_resolver = generated_resolver.replace(/\s/g, ""); - let test_resolver = data_test.remove_assoc_to_many_fieldMutation_resolver.replace( - /\s/g, - "" - ); + let test_resolver = + data_test.remove_assoc_to_many_fieldMutation_resolver.replace(/\s/g, ""); expect(g_resolver).to.have.string(test_resolver); }); @@ -1832,10 +1826,8 @@ describe("Refactor associations - add / update SQL models", function () { let opts = funks.getOptions(models_refactoring.accession); let generated_resolver = await funks.generateJs("create-models", opts); let g_resolver = generated_resolver.replace(/\s/g, ""); - let test_resolver = data_test._addAssoc_to_one_fieldMutation_sql_model.replace( - /\s/g, - "" - ); + let test_resolver = + data_test._addAssoc_to_one_fieldMutation_sql_model.replace(/\s/g, ""); expect(g_resolver).to.have.string(test_resolver); }); @@ -1843,10 +1835,8 @@ describe("Refactor associations - add / update SQL models", function () { let opts = funks.getOptions(models_refactoring.accession); let generated_resolver = await funks.generateJs("create-models", opts); let g_resolver = generated_resolver.replace(/\s/g, ""); - let test_resolver = data_test._removeAssoc_to_one_fieldMutation_sql_model.replace( - /\s/g, - "" - ); + let test_resolver = + data_test._removeAssoc_to_one_fieldMutation_sql_model.replace(/\s/g, ""); expect(g_resolver).to.have.string(test_resolver); }); }); @@ -3080,3 +3070,109 @@ describe("Trino/Presto Unit Test", () => { testCompare(generated_model, data_test.trino_adapter_readById); }); }); + +describe("Neo4j Unit Test", function () { + let data_test = require("./unit_test_misc/test-describe/neo4j-unittest"); + + it("neo4j model - movie constructor", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare(generated_model, data_test.movie_constructor); + }); + + it("neo4j model - movie readById", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare(generated_model, data_test.movie_readById); + }); + + it("neo4j model - movie countRecords", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare(generated_model, data_test.movie_countRecords); + }); + + it("neo4j model - movie readAll", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare(generated_model, data_test.movie_readAll); + }); + + it("neo4j model - movie readAllCursor", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare(generated_model, data_test.movie_readAllCursor); + }); + + it("neo4j model - movie addOne", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare(generated_model, data_test.movie_addOne); + }); + + it("neo4j model - movie deleteOne", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare(generated_model, data_test.movie_deleteOne); + }); + + it("neo4j model - movie updateOne", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare(generated_model, data_test.movie_updateOne); + }); + + it("neo4j model - movie bulkAddCsv", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare(generated_model, data_test.movie_bulkAddCsv); + }); + + it("neo4j model - fieldMutations toOne - add director to movie", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare(generated_model, data_test.movie_fieldMutation_add_director); + }); + + it("neo4j model - fieldMutations toOne - remove director from movie", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare(generated_model, data_test.movie_fieldMutation_remove_director); + }); + + it("neo4j model - fieldMutations toMany - add actor to movie", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare(generated_model, data_test.movie_fieldMutation_add_actor); + }); + + it("neo4j model - fieldMutations toMany - remove actor from movie", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare(generated_model, data_test.movie_fieldMutation_remove_actor); + }); + + it("neo4j model - fieldMutations bulkAssociation - add director to movie", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare( + generated_model, + data_test.movie_fieldMutation_bulkAssociate_add + ); + }); + + it("neo4j model - fieldMutations bulkAssociation - remove director from movie", async function () { + let opts = funks.getOptions(models_neo4j.movie); + let generated_model = await funks.generateJs("create-models-neo4j", opts); + testCompare( + generated_model, + data_test.movie_fieldMutation_bulkAssociate_remove + ); + }); + + it("neo4j adapter - dist_movie_instance1 readById ", async function () { + let opts = funks.getOptions(models_neo4j.dist_movie_instance1); + let generated_model = await funks.generateJs("create-neo4j-adapter", opts); + testCompare(generated_model, data_test.neo4j_adapter_readById); + }); +}); diff --git a/test/testenv_cli.sh b/test/testenv_cli.sh index 5fba6eee..3275bf17 100644 --- a/test/testenv_cli.sh +++ b/test/testenv_cli.sh @@ -98,7 +98,7 @@ fi # 1. Stop docker containers and remove anonymous volumes # 2. Re-start the docker containers if [[ $OPT_RESTART_DOCKER == "true" ]]; then - docker-compose -f "${TEST_DIR}/integration_test_misc/docker-compose-test.yml" down -v + UID_GID="$(id -u):$(id -g)" docker-compose -f "${TEST_DIR}/integration_test_misc/docker-compose-test.yml" down -v bash "${TEST_DIR}/testenv_docker_up.sh" exit 0 fi @@ -114,6 +114,7 @@ if [[ $OPT_RUN_TESTS == "true" ]]; then mocha "${TEST_DIR}/mocha_integration_amazon_s3.test.js" mocha --timeout 10000 "${TEST_DIR}/mocha_integration_trino.test.js" mocha --timeout 10000 "${TEST_DIR}/mocha_integration_presto.test.js" + mocha "${TEST_DIR}/mocha_integration_neo4j.test.js" # 1. Remove docker containers, images, and volumes # 2. Remove the testing environment @@ -132,7 +133,7 @@ fi # 4. Run integration tests # 5. Perform a full cleanup (optionally disabled) if [[ $OPT_GENCODE_RUNTESTS == "true" ]]; then - docker-compose -f "${TEST_DIR}/integration_test_misc/docker-compose-test.yml" down -v + UID_GID="$(id -u):$(id -g)" docker-compose -f "${TEST_DIR}/integration_test_misc/docker-compose-test.yml" down -v bash "${TEST_DIR}/testenv_generate_code.sh" bash "${TEST_DIR}/testenv_sync.sh" bash "${TEST_DIR}/testenv_docker_up.sh" @@ -142,6 +143,7 @@ if [[ $OPT_GENCODE_RUNTESTS == "true" ]]; then mocha "${TEST_DIR}/mocha_integration_amazon_s3.test.js" mocha --timeout 10000 "${TEST_DIR}/mocha_integration_trino.test.js" mocha --timeout 10000 "${TEST_DIR}/mocha_integration_presto.test.js" + mocha "${TEST_DIR}/mocha_integration_neo4j.test.js" # 1. Remove docker containers, images, and volumes # 2. Remove the testing environment @@ -172,6 +174,7 @@ if [[ $DEFAULT_RUN == "true" ]]; then mocha "${TEST_DIR}/mocha_integration_amazon_s3.test.js" mocha --timeout 10000 "${TEST_DIR}/mocha_integration_trino.test.js" mocha --timeout 10000 "${TEST_DIR}/mocha_integration_presto.test.js" + mocha "${TEST_DIR}/mocha_integration_neo4j.test.js" # 1. Remove docker containers, images, and volumes # 2. Remove the testing environment diff --git a/test/testenv_docker_up.sh b/test/testenv_docker_up.sh index b323c690..04d49a43 100644 --- a/test/testenv_docker_up.sh +++ b/test/testenv_docker_up.sh @@ -35,7 +35,7 @@ source "${SCRIPT_DIR}/testenv_constants.sh" printBlockHeader "START" "UP DOCKER CONTAINERS" # Up detached docker containers -docker-compose \ +UID_GID="$(id -u):$(id -g)" docker-compose \ -f "${TEST_DIR}/integration_test_misc/docker-compose-test.yml" up -d \ --force-recreate \ --remove-orphans \ diff --git a/test/testenv_remove.sh b/test/testenv_remove.sh index b0efd575..58a0da00 100644 --- a/test/testenv_remove.sh +++ b/test/testenv_remove.sh @@ -10,7 +10,7 @@ source "${SCRIPT_DIR}/testenv_constants.sh" printBlockHeader "START" "REMOVE TESTING ENVIRONMENT" # Remove docker containers, images, and volumes -docker-compose -f "${TEST_DIR}/integration_test_misc/docker-compose-test.yml" down -v --rmi all +UID_GID="$(id -u):$(id -g)" docker-compose -f "${TEST_DIR}/integration_test_misc/docker-compose-test.yml" down -v --rmi all # Remove testing environment echo "Removing ${ENV_DIR}" diff --git a/test/unit_test_misc/data_models_neo4j.js b/test/unit_test_misc/data_models_neo4j.js new file mode 100644 index 00000000..49cc6546 --- /dev/null +++ b/test/unit_test_misc/data_models_neo4j.js @@ -0,0 +1,70 @@ +module.exports.movie = { + model: "movie", + storageType: "neo4j", + attributes: { + movie_id: "String", + release: "DateTime", + runtime: "Int", + box_office: "Float", + is_adult: "Boolean", + genres: "[String]", + votes: "[Int]", + director_id: "String", + actor_ids: "[String]", + }, + associations: { + director: { + type: "to_one", + target: "director", + targetKey: "director_id", + keyIn: "movie", + targetStorageType: "neo4j", + label: "director_name", + }, + actor: { + type: "to_many", + reverseAssociationType: "to_many", + target: "actor", + targetKey: "movie_ids", + sourceKey: "actor_ids", + keyIn: "movie", + targetStorageType: "neo4j", + }, + unique_review: { + type: "to_one", + target: "review", + targetKey: "movie_id", + keyIn: "tracker", + targetStorageType: "neo4j", + }, + }, + internalId: "movie_id", +}; + +module.exports.dist_movie_instance1 = { + model: "dist_movie", + storageType: "neo4j-adapter", + adapterName: "dist_movie_instance1", + regex: "instance1", + attributes: { + movie_id: "String", + release: "DateTime", + runtime: "Int", + box_office: "Float", + is_adult: "Boolean", + genres: "[String]", + votes: "[Int]", + director_id: "String", + }, + associations: { + dist_director: { + type: "to_one", + target: "dist_director", + targetKey: "director_id", + keyIn: "dist_movie", + targetStorageType: "distributed-data-model", + }, + }, + + internalId: "movie_id", +}; diff --git a/test/unit_test_misc/test-describe/amazonS3-unittest.js b/test/unit_test_misc/test-describe/amazonS3-unittest.js index 68656915..9ce3afad 100644 --- a/test/unit_test_misc/test-describe/amazonS3-unittest.js +++ b/test/unit_test_misc/test-describe/amazonS3-unittest.js @@ -91,7 +91,7 @@ static async readAllCursor(search, order, pagination, benignErrorReporter){ query += \` LIMIT \${pagination.first+1}\`; } - let records = null; + let records = []; try { const s3 = await this.storageHandler; const result = await s3 diff --git a/test/unit_test_misc/test-describe/cassandra-storagetype.js b/test/unit_test_misc/test-describe/cassandra-storagetype.js index 0189285b..e79108bb 100644 --- a/test/unit_test_misc/test-describe/cassandra-storagetype.js +++ b/test/unit_test_misc/test-describe/cassandra-storagetype.js @@ -458,6 +458,7 @@ static readAllCursor(search, order, pagination, authorizedAdapters, benignErrorR case 'amazon-s3-adapter': case 'trino-adapter': case 'presto-adapter': + case 'neo4j-adapter': case 'zendro-webservice-adapter': return adapter.readAllCursor(search, order, pagination, benignErrorReporter); case 'cassandra-adapter': diff --git a/test/unit_test_misc/test-describe/distributed-models.js b/test/unit_test_misc/test-describe/distributed-models.js index 587e8e72..bb1b45cf 100644 --- a/test/unit_test_misc/test-describe/distributed-models.js +++ b/test/unit_test_misc/test-describe/distributed-models.js @@ -169,6 +169,7 @@ static countRecords(search, authorizedAdapters, benignErrorReporter, searchAutho case 'amazon-s3-adapter': case 'trino-adapter': case 'presto-adapter': + case 'neo4j-adapter': case 'zendro-webservice-adapter': return adapter.countRecords(search, benignErrorReporter); case 'cassandra-adapter': @@ -247,6 +248,7 @@ static readAllCursor(search, order, pagination, authorizedAdapters, benignErrorR case 'amazon-s3-adapter': case 'trino-adapter': case 'presto-adapter': + case 'neo4j-adapter': case 'zendro-webservice-adapter': return adapter.readAllCursor(search, order, pagination, benignErrorReporter); case 'cassandra-adapter': diff --git a/test/unit_test_misc/test-describe/handle-error-ddm.js b/test/unit_test_misc/test-describe/handle-error-ddm.js index ba0620bc..fa657eef 100644 --- a/test/unit_test_misc/test-describe/handle-error-ddm.js +++ b/test/unit_test_misc/test-describe/handle-error-ddm.js @@ -49,6 +49,7 @@ static countRecords(search, authorizedAdapters, benignErrorReporter, searchAutho case 'amazon-s3-adapter': case 'trino-adapter': case 'presto-adapter': + case 'neo4j-adapter': case 'zendro-webservice-adapter': return adapter.countRecords(search, benignErrorReporter); case 'cassandra-adapter': @@ -128,6 +129,7 @@ static readAllCursor(search, order, pagination, authorizedAdapters, benignErrorR case 'amazon-s3-adapter': case 'trino-adapter': case 'presto-adapter': + case 'neo4j-adapter': case 'zendro-webservice-adapter': return adapter.readAllCursor(search, order, pagination, benignErrorReporter); case 'cassandra-adapter': diff --git a/test/unit_test_misc/test-describe/neo4j-unittest.js b/test/unit_test_misc/test-describe/neo4j-unittest.js new file mode 100644 index 00000000..ed0655c6 --- /dev/null +++ b/test/unit_test_misc/test-describe/neo4j-unittest.js @@ -0,0 +1,634 @@ +module.exports.movie_constructor = ` +constructor(input) { + for (let key of Object.keys(input)) { + this[key] = input[key]; + } +} +`; + +module.exports.movie_readById = ` +static async readById(id) { + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.READ, + }); + try { + const result = await session.run( + \`MATCH (n:Movie {\${this.idAttribute()}:\$id}) RETURN n\`, { + id: id + } + ); + if (result.records.length === 0) { + throw new Error(\`Record with ID = "\${id}" does not exist\`); + } + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return validatorUtil.validateData( + "validateAfterRead", + this, + new movie(node.properties) + ); + } catch (error) { + throw error; + } finally { + await session.close(); + } +} +`; + +module.exports.movie_countRecords = ` +static async countRecords(search) { + const whereOptions = neo4jHelper.searchConditionsToNeo4j( + search, + definition + ); + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.READ, + }); + try { + const result = await session.run( + \`MATCH (n:Movie) \${whereOptions} RETURN COUNT(n)\` + ); + const singleRecord = result.records[0]; + const num = singleRecord.get(0); + return num; + } catch (error) { + throw error; + } finally { + await session.close(); + } +} +`; + +module.exports.movie_readAll = ` +static async readAll(search, order, pagination, benignErrorReporter) { + //use default BenignErrorReporter if no BenignErrorReporter defined + benignErrorReporter = + errorHelper.getDefaultBenignErrorReporterIfUndef(benignErrorReporter); + // build the filter object for limit-offset-based pagination + const whereOptions = neo4jHelper.searchConditionsToNeo4j( + search, + definition + ); + const orderOptions = neo4jHelper.orderConditionsToNeo4j( + order, + this.idAttribute(), + true + ); + + const limit = pagination.limit; + const offset = pagination.offset ? pagination.offset : 0; + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.READ, + }); + try { + const result = await session.run( + \`MATCH (n:Movie) \${whereOptions} RETURN n \${orderOptions} SKIP \${offset} LIMIT \${limit} \` + ); + const nodes = result.records.map((res) => res.get(0).properties); + return validatorUtil.bulkValidateData( + "validateAfterRead", + this, + nodes, + benignErrorReporter + ); + } catch (error) { + throw error; + } finally { + await session.close(); + } +} +`; + +module.exports.movie_readAllCursor = ` +static async readAllCursor(search, order, pagination, benignErrorReporter) { + //use default BenignErrorReporter if no BenignErrorReporter defined + benignErrorReporter = + errorHelper.getDefaultBenignErrorReporterIfUndef(benignErrorReporter); + let isForwardPagination = helper.isForwardPagination(pagination); + // build the whereOptions. + let filter = neo4jHelper.searchConditionsToNeo4j(search, definition); + let newOrder = isForwardPagination ? + order : + helper.reverseOrderConditions(order); + // depending on the direction build the order object + let sort = neo4jHelper.orderConditionsToNeo4j( + newOrder, + this.idAttribute(), + isForwardPagination + ); + let orderFields = newOrder ? newOrder.map((x) => x.field) : []; + // extend the filter for the given order and cursor + filter = neo4jHelper.cursorPaginationArgumentsToNeo4j( + pagination, + sort, + filter, + orderFields, + this.idAttribute(), + definition.attributes + ); + + // add +1 to the LIMIT to get information about following pages. + let limit = helper.isNotUndefinedAndNotNull(pagination.first) ? + pagination.first + 1 : + helper.isNotUndefinedAndNotNull(pagination.last) ? + pagination.last + 1 : + undefined; + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.READ, + }); + let nodes = []; + try { + const result = await session.run( + \`MATCH (n:Movie) \${filter} RETURN n \${sort} LIMIT \${limit}\` + ); + nodes = result.records.map((res) => new movie(res.get(0).properties)); + nodes = await validatorUtil.bulkValidateData( + "validateAfterRead", + this, + nodes, + benignErrorReporter + ); + } catch (error) { + throw error; + } + + // get the first record (if exists) in the opposite direction to determine pageInfo. + // if no cursor was given there is no need for an extra query as the results will start at the first (or last) page. + let oppNodes = []; + if (pagination && (pagination.after || pagination.before)) { + // reverse the pagination Arguement. after -> before; set first/last to 0, so LIMIT 1 is executed in the reverse Search + let oppPagination = helper.reversePaginationArgument({ + ...pagination, + includeCursor: false, + }); + let oppForwardPagination = helper.isForwardPagination(oppPagination); + // build the filter object. + let oppFilter = neo4jHelper.searchConditionsToNeo4j(search, definition); + + let oppOrder = oppForwardPagination ? + order : + helper.reverseOrderConditions(order); + // depending on the direction build the order object + let oppSort = neo4jHelper.orderConditionsToNeo4j( + oppOrder, + this.idAttribute(), + oppForwardPagination + ); + let oppOrderFields = oppOrder ? oppOrder.map((x) => x.field) : []; + // extend the filter for the given order and cursor + oppFilter = neo4jHelper.cursorPaginationArgumentsToNeo4j( + oppPagination, + oppSort, + oppFilter, + oppOrderFields, + this.idAttribute(), + definition.attributes + ); + // add +1 to the LIMIT to get information about following pages. + let oppLimit = helper.isNotUndefinedAndNotNull(oppPagination.first) ? + oppPagination.first + 1 : + helper.isNotUndefinedAndNotNull(oppPagination.last) ? + oppPagination.last + 1 : + undefined; + + try { + const oppResult = await session.run( + \`MATCH (n:Movie) \${oppFilter} RETURN n \${oppSort} LIMIT \${oppLimit}\` + ); + oppNodes = oppResult.records.map( + (res) => new movie(res.get(0).properties) + ); + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + + // build the graphql Connection Object + let edges = nodes.map((res) => { + return { + node: res, + cursor: res.base64Enconde(), + }; + }); + const pageInfo = helper.buildPageInfo(edges, oppNodes, pagination); + return { + edges, + pageInfo, + movies: edges.map((edge) => edge.node) + }; +} +`; + +module.exports.movie_addOne = ` +static async addOne(input) { + // validate input + await validatorUtil.validateData("validateForCreate", this, input); + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + try { + delete input.skipAssociationsExistenceChecks; + input = neo4jHelper.processDateTime(input, definition.attributes); + + const result = await session.run(\`CREATE (a:Movie $props) RETURN a\`, { + props: input, + }); + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return new movie(node.properties); + } catch (error) { + throw error; + } finally { + await session.close(); + } +} +`; + +module.exports.movie_deleteOne = ` +static async deleteOne(id) { + //validate id + await validatorUtil.validateData("validateForDelete", this, id); + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + try { + const result = await session.run( + \`MATCH (n:Movie {\${this.idAttribute()}:$id}) DELETE n\`, { + id: id + } + ); + if (result.records.length !== 0) { + throw new Error(\`Record with ID = \${id} has not been deleted!\`); + } + return "Item successfully deleted"; + } catch (error) { + console.log(\`Record with ID = \${id} could not be deleted\`); + throw error; + } finally { + await session.close(); + } +} +`; + +module.exports.movie_updateOne = ` +static async updateOne(input) { + //validate input + await validatorUtil.validateData("validateForUpdate", this, input); + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + const id = input[this.idAttribute()]; + try { + delete input.skipAssociationsExistenceChecks; + delete input[this.idAttribute()]; + input = neo4jHelper.processDateTime(input, definition.attributes); + + const result = await session.run( + \`MATCH (n:Movie {\${this.idAttribute()}:$id}) SET n+=$props RETURN n\`, { + id: id, + props: input + } + ); + if (result.records.length !== 1) { + throw new Error(\`Record with ID = \${id} has not been updated!\`); + } + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return new movie(node.properties); + } catch (error) { + console.log(\`Record with ID = \${id} could not be updated\`); + throw error; + } finally { + await session.close(); + } +} +`; + +module.exports.movie_bulkAddCsv = ` +static async bulkAddCsv(context) { + let field_delim = config.fieldDelimiter ?? ","; + let array_delim = config.arrayDelimiter ?? ";"; + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + try { + let query = \`LOAD CSV WITH HEADERS FROM 'file:///movie.csv' AS line FIELDTERMINATOR '\${field_delim}' CREATE (:Movie {\`; + for (let attr of Object.keys(definition.attributes)) { + let type = definition.attributes[attr].replace(/\\s+/g, ""); + if (type[0] === "[") { + type = type.slice(1, type.length - 1); + if (type === "Int") { + query += \`\${attr}: [i in split(line.\${attr}, "\${array_delim}") | toInteger(i)], \`; + } else if (type === "Boolean") { + query += \`\${attr}: [i in split(line.\${attr}, "\${array_delim}") | toBoolean(i)], \`; + } else if (type === "Float") { + query += \`\${attr}: [i in split(line.\${attr}, "\${array_delim}") | toFloat(i)], \`; + } else { + query += \`\${attr}: split(line.\${attr}, "\${array_delim}"), \`; + } + } else { + if (type === "Int") { + query += \`\${attr}: toInteger(line.\${attr}), \`; + } else if (type === "Boolean") { + query += \`\${attr}: toBoolean(line.\${attr}), \`; + } else if (type === "Float") { + query += \`\${attr}: toFloat(line.\${attr}), \`; + } else { + query += \`\${attr}: line.\${attr}, \`; + } + } + } + query = query.slice(0, query.length - 2) + "})"; + const result = await session.run(query); + return \`Successfully upload file\`; + } catch (e) { + throw new Error(e); + } finally { + await session.close(); + } +`; + +module.exports.movie_fieldMutation_add_director = ` +static async add_director_id(movie_id, director_id) { + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + let foreignKey = \`MATCH (n:Movie ) WHERE n.movie_id = $id + SET n.director_id = $target RETURN head(collect(n))\` + + let create_relationships = \`MATCH (a:Movie), (b:Director) + WHERE a.movie_id = $id AND b.\${models.director.idAttribute()} = $target + CREATE (a)-[r:\${"director".toUpperCase() + "_EDGE"}]->(b)\` + try { + const result = await session.run(foreignKey, { + id: movie_id, + target: director_id + }); + await session.run(create_relationships, { + id: movie_id, + target: director_id, + }) + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return new movie(node) + } catch (error) { + throw error; + } finally { + await session.close(); + } +} +`; + +module.exports.movie_fieldMutation_remove_director = ` +static async remove_director_id(movie_id, director_id) { + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + let foreignKey = \`MATCH (n:Movie ) WHERE n.movie_id = $id + SET n.director_id = $target RETURN head(collect(n))\` + + let delete_relationships = \`MATCH (a:Movie)-[r:\${"director".toUpperCase() + "_EDGE"}]-> (b:Director) + WHERE a.movie_id = $id AND b.\${models.director.idAttribute()} = $target + DELETE r\` + try { + const result = await session.run(foreignKey, { + id: movie_id, + target: null + }); + await session.run(delete_relationships, { + id: movie_id, + target: director_id, + }) + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return new movie(node) + } catch (error) { + throw error; + } finally { + await session.close(); + } +} +`; + +module.exports.movie_fieldMutation_add_actor = ` +static async add_actor_ids(movie_id, actor_ids, benignErrorReporter, handle_inverse = true) { + //handle inverse association + if (handle_inverse) { + let promises = []; + actor_ids.forEach(idx => { + promises.push(models.actor.add_movie_ids(idx, [\`\${movie_id}\`], benignErrorReporter, false)); + }); + await Promise.all(promises); + } + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + let foreignKey = \`MATCH (n:Movie ) WHERE n.movie_id = $id + SET n.actor_ids = $updated_ids\` + + let create_relationships = \`MATCH (a:Movie), (b:Actor) + WHERE a.movie_id = $id AND b.\${models.actor.idAttribute()} IN $source + CREATE (a)-[r:\${"actor".toUpperCase() + "_EDGE"}]->(b)\` + try { + let record = await this.readById(movie_id); + + if (record !== null) { + let updated_ids = helper.unionIds(record.actor_ids, actor_ids); + await session.run(foreignKey, { + id: movie_id, + updated_ids: updated_ids + }); + + await session.run(create_relationships, { + id: movie_id, + source: actor_ids, + }) + } + } catch (error) { + throw error; + } finally { + await session.close(); + } +} +`; + +module.exports.movie_fieldMutation_remove_actor = ` +static async remove_actor_ids(movie_id, actor_ids, benignErrorReporter, handle_inverse = true) { + //handle inverse association + if (handle_inverse) { + let promises = []; + actor_ids.forEach(idx => { + promises.push(models.actor.remove_movie_ids(idx, [\`\${movie_id}\`], benignErrorReporter, false)); + }); + await Promise.all(promises); + } + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + let foreignKey = \`MATCH (n:Movie ) WHERE n.movie_id = $id + SET n.actor_ids = $updated_ids\` + + let delete_relationships = \`MATCH (a:Movie)-[r:\${"actor".toUpperCase() + "_EDGE"}]-> (b:Actor) + WHERE a.movie_id = $id AND b.\${models.actor.idAttribute()} IN $source + DELETE r\` + try { + let record = await this.readById(movie_id); + + if (record !== null) { + let updated_ids = helper.differenceIds(record.actor_ids, actor_ids); + await session.run(foreignKey, { + id: movie_id, + updated_ids: updated_ids + }); + + await session.run(delete_relationships, { + id: movie_id, + source: actor_ids, + }) + } + } catch (error) { + throw error; + } finally { + await session.close(); + } +} +`; + +module.exports.movie_fieldMutation_bulkAssociate_add = ` +static async bulkAssociateMovieWithDirector_id(bulkAssociationInput, benignErrorReporter) { + let mappedForeignKeys = helper.mapForeignKeysToPrimaryKeyArray(bulkAssociationInput, "movie_id", "director_id"); + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + let foreignKey = \`MATCH (n:Movie) WHERE n.movie_id IN $id + SET n.director_id = $target\` + + let create_relationships = \`MATCH (a:Movie), (b:Director) + WHERE a.movie_id IN $id AND b.director_id = $target + CREATE (a)-[r:\${"director".toUpperCase() + "_EDGE"}]->(b)\` + try { + for (let { + director_id, + movie_id + } of mappedForeignKeys) { + await session.run(foreignKey, { + id: movie_id, + target: director_id + }) + await session.run(create_relationships, { + id: movie_id, + target: director_id, + }) + } + } catch (error) { + throw error; + } finally { + await session.close(); + } + + return "Records successfully updated!" +} +`; +module.exports.movie_fieldMutation_bulkAssociate_remove = ` +static async bulkDisAssociateMovieWithDirector_id(bulkAssociationInput, benignErrorReporter) { + let mappedForeignKeys = helper.mapForeignKeysToPrimaryKeyArray(bulkAssociationInput, "movie_id", "director_id"); + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + let foreignKey = \`MATCH (n:Movie) WHERE n.movie_id IN $id + SET n.director_id = $target\` + + let delete_relationships = \`MATCH (a:Movie)-[r:\${"director".toUpperCase() + "_EDGE"}]-> (b:Director) + WHERE a.movie_id IN $id AND b.director_id = $target + DELETE r\` + try { + for (let { + director_id, + movie_id + } of mappedForeignKeys) { + await session.run(foreignKey, { + id: movie_id, + target: null + }) + await session.run(delete_relationships, { + id: movie_id, + target: director_id, + }) + } + } catch (error) { + throw error; + } finally { + await session.close(); + } + + return "Records successfully updated!" +} +`; + +module.exports.neo4j_adapter_readById = ` +static async readById(id){ + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.READ, + }); + try { + const result = await session.run( + \`MATCH (n:Dist_movie {\${this.idAttribute()}:\$id}) RETURN n\`, { + id: id + } + ); + if (result.records.length === 0) { + throw new Error(\`Record with ID = "\${id}" does not exist\`); + } + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return validatorUtil.validateData( + "validateAfterRead", + this, + new dist_movie_instance1(node.properties) + ); + } catch (error) { + throw error; + } finally { + await session.close(); + } +} +`; diff --git a/test/unit_test_misc/test-describe/trino-unittest.js b/test/unit_test_misc/test-describe/trino-unittest.js index ade313b7..8a2d56ea 100644 --- a/test/unit_test_misc/test-describe/trino-unittest.js +++ b/test/unit_test_misc/test-describe/trino-unittest.js @@ -126,7 +126,7 @@ static async readAllCursor(search, order, pagination, benignErrorReporter) { \${filter} \${sort} LIMIT \${limit}\`; - let result = null; + let result = []; const client = await this.storageHandler; result = await prestoHelper.queryData(query, client); diff --git a/views/create-amazonS3-adapter.ejs b/views/create-amazonS3-adapter.ejs index c93e2879..bdc64f61 100644 --- a/views/create-amazonS3-adapter.ejs +++ b/views/create-amazonS3-adapter.ejs @@ -5,9 +5,7 @@ const validatorUtil = require("../../utils/validatorUtil"); const helper = require("../../utils/helper"); const errorHelper = require("../../utils/errors"); const fs = require("fs"); -const config = require("../../config/data_models_storage_config.json")[ - "default-amazonS3" -]; +const config = require("../../config/data_models_storage_config.json")["<%- database -%>"]; const amazonS3Helper = require("../../utils/amazonS3_helper"); const path = require("path"); const uuidv4 = require("uuidv4").uuid; @@ -220,7 +218,7 @@ module.exports = class <%- adapterName -%> { query += ` LIMIT ${pagination.first+1}`; } - let records = null; + let records = []; try { const s3 = await this.storageHandler; const result = await s3 diff --git a/views/create-distributed-model.ejs b/views/create-distributed-model.ejs index 37432e94..e7f58011 100644 --- a/views/create-distributed-model.ejs +++ b/views/create-distributed-model.ejs @@ -137,6 +137,7 @@ module.exports = class <%- nameLc -%>{ case 'amazon-s3-adapter': case 'trino-adapter': case 'presto-adapter': + case 'neo4j-adapter': case 'zendro-webservice-adapter': return adapter.countRecords(search, benignErrorReporter); case 'cassandra-adapter': @@ -213,6 +214,7 @@ module.exports = class <%- nameLc -%>{ case 'amazon-s3-adapter': case 'trino-adapter': case 'presto-adapter': + case 'neo4j-adapter': case 'zendro-webservice-adapter': return adapter.readAllCursor(search, order, pagination, benignErrorReporter); case 'cassandra-adapter': diff --git a/views/create-models-amazonS3.ejs b/views/create-models-amazonS3.ejs index c3b18fdf..c0141e7e 100644 --- a/views/create-models-amazonS3.ejs +++ b/views/create-models-amazonS3.ejs @@ -217,7 +217,7 @@ module.exports = class <%- nameLc -%> { query += ` LIMIT ${pagination.first+1}`; } - let records = null; + let records = []; try { const s3 = await this.storageHandler; const result = await s3 diff --git a/views/create-models-neo4j.ejs b/views/create-models-neo4j.ejs new file mode 100644 index 00000000..7a52f9dc --- /dev/null +++ b/views/create-models-neo4j.ejs @@ -0,0 +1,530 @@ +"use strict"; + +const _ = require("lodash"); +const validatorUtil = require("../../utils/validatorUtil"); +const path = require("path"); +const helper = require("../../utils/helper"); +const neo4jHelper = require("../../utils/neo4j_helper"); +const errorHelper = require("../../utils/errors"); +const neo4j = require("neo4j-driver"); +const config = require("../../config/data_models_storage_config.json")["<%- database -%>"]; +const models = require(path.join(__dirname, "..", "index.js")); + +// An exact copy of the the model definition that comes from the .json file +const definition = <%- definition -%>; + +/** + * module - Creates a class for Neo4j data model + * + */ + +module.exports = class <%- nameLc -%> { + constructor(input) { + for (let key of Object.keys(input)) { + this[key] = input[key]; + } + } + + /** + * Get the storage handler, which is a static property of the data model class. + * @returns connected neo4j client + */ + get storageHandler() { + return <%- nameLc -%>.storageHandler; + } + + /** + * name - Getter for the name attribute + * + * This attribute is needed by the models' index + * @return {string} The name of the model + */ + static get name() { + return "<%- nameLc -%>"; + } + + /** + * readById - The model implementation for reading a single record given by its ID + * + * This method is the implementation for reading a single record for the neo4j storage type, based on neo4j node driver. + * @param {string} id - The ID of the requested record + * @return {object} The requested record as an object with the type <%- nameLc -%>, or an error object if the validation after reading fails + * @throws {Error} If the requested record does not exist + */ + static async readById(id) { + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.READ, + }); + try { + const result = await session.run( + `MATCH (n:<%- nameCp -%> {${this.idAttribute()}:$id}) RETURN n`, + { id: id } + ); + if (result.records.length === 0) { + throw new Error(`Record with ID = "${id}" does not exist`); + } + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return validatorUtil.validateData( + "validateAfterRead", + this, + new <%- nameLc -%>(node.properties) + ); + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + + /** + * countRecords - The model implementation for counting the number of records, possibly restricted by a search term + * + * This method is the implementation for counting the number of records that fulfill a given condition, or for all records in the table, + * for the Neo4j storage type, based on Neo4j node driver. + * @param {object} search - The search term that restricts the set of records to be counted - if undefined, all records in the table + * @param {BenignErrorReporter} benignErrorReporter can be used to generate the standard + * @return {number} The number of records that fulfill the condition, or of all records in the table + */ + static async countRecords(search) { + const whereOptions = neo4jHelper.searchConditionsToNeo4j( + search, + definition + ); + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.READ, + }); + try { + const result = await session.run( + `MATCH (n:<%- nameCp -%>) ${whereOptions} RETURN COUNT(n)` + ); + const singleRecord = result.records[0]; + const num = singleRecord.get(0); + return num; + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + + /** + * readAll - The model implementation for searching for records in Neo4j. This method uses limit-offset-based pagination. + * + * @param {object} search - Search argument for filtering records + * @param {array} order - Type of sorting (ASC, DESC) for each field + * @param {object} pagination - Offset and limit to get the records from and to respectively + * @param {BenignErrorReporter} - benignErrorReporter can be used to generate the standard + * @return {array} Array of records holding conditions specified by search, order and pagination argument + */ + static async readAll(search, order, pagination, benignErrorReporter) { + //use default BenignErrorReporter if no BenignErrorReporter defined + benignErrorReporter = + errorHelper.getDefaultBenignErrorReporterIfUndef(benignErrorReporter); + // build the filter object for limit-offset-based pagination + const whereOptions = neo4jHelper.searchConditionsToNeo4j( + search, + definition + ); + const orderOptions = neo4jHelper.orderConditionsToNeo4j( + order, + this.idAttribute(), + true + ); + + const limit = pagination.limit; + const offset = pagination.offset ? pagination.offset : 0; + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.READ, + }); + try { + const result = await session.run( + `MATCH (n:<%- nameCp -%>) ${whereOptions} RETURN n ${orderOptions} SKIP ${offset} LIMIT ${limit} ` + ); + const nodes = result.records.map((res) => res.get(0).properties); + return validatorUtil.bulkValidateData( + "validateAfterRead", + this, + nodes, + benignErrorReporter + ); + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + + /** + * readAllCursor - The model implementation for searching for records in Neo4j. This method uses cursor based pagination. + * + * @param {object} search - The search condition for which records shall be fetched + * @param {array} order - Type of sorting (ASC, DESC) for each field + * @param {object} pagination - The parameters for pagination, which can be used to get a subset of the requested record set. + * @param {BenignErrorReporter} benignErrorReporter can be used to generate the standard + * @return {object} The set of records, possibly constrained by pagination, with full cursor information for all records + */ + static async readAllCursor(search, order, pagination, benignErrorReporter) { + //use default BenignErrorReporter if no BenignErrorReporter defined + benignErrorReporter = + errorHelper.getDefaultBenignErrorReporterIfUndef(benignErrorReporter); + let isForwardPagination = helper.isForwardPagination(pagination); + // build the whereOptions. + let filter = neo4jHelper.searchConditionsToNeo4j(search, definition); + let newOrder = isForwardPagination + ? order + : helper.reverseOrderConditions(order); + // depending on the direction build the order object + let sort = neo4jHelper.orderConditionsToNeo4j( + newOrder, + this.idAttribute(), + isForwardPagination + ); + let orderFields = newOrder ? newOrder.map((x) => x.field) : []; + // extend the filter for the given order and cursor + filter = neo4jHelper.cursorPaginationArgumentsToNeo4j( + pagination, + sort, + filter, + orderFields, + this.idAttribute(), + definition.attributes + ); + + // add +1 to the LIMIT to get information about following pages. + let limit = helper.isNotUndefinedAndNotNull(pagination.first) + ? pagination.first + 1 + : helper.isNotUndefinedAndNotNull(pagination.last) + ? pagination.last + 1 + : undefined; + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.READ, + }); + let nodes = []; + try { + const result = await session.run( + `MATCH (n:<%- nameCp -%>) ${filter} RETURN n ${sort} LIMIT ${limit}` + ); + nodes = result.records.map((res) => new <%- nameLc -%>(res.get(0).properties)); + nodes = await validatorUtil.bulkValidateData( + "validateAfterRead", + this, + nodes, + benignErrorReporter + ); + } catch (error) { + throw error; + } + + // get the first record (if exists) in the opposite direction to determine pageInfo. + // if no cursor was given there is no need for an extra query as the results will start at the first (or last) page. + let oppNodes = []; + if (pagination && (pagination.after || pagination.before)) { + // reverse the pagination Arguement. after -> before; set first/last to 0, so LIMIT 1 is executed in the reverse Search + let oppPagination = helper.reversePaginationArgument({ + ...pagination, + includeCursor: false, + }); + let oppForwardPagination = helper.isForwardPagination(oppPagination); + // build the filter object. + let oppFilter = neo4jHelper.searchConditionsToNeo4j(search, definition); + + let oppOrder = oppForwardPagination + ? order + : helper.reverseOrderConditions(order); + // depending on the direction build the order object + let oppSort = neo4jHelper.orderConditionsToNeo4j( + oppOrder, + this.idAttribute(), + oppForwardPagination + ); + let oppOrderFields = oppOrder ? oppOrder.map((x) => x.field) : []; + // extend the filter for the given order and cursor + oppFilter = neo4jHelper.cursorPaginationArgumentsToNeo4j( + oppPagination, + oppSort, + oppFilter, + oppOrderFields, + this.idAttribute(), + definition.attributes + ); + // add +1 to the LIMIT to get information about following pages. + let oppLimit = helper.isNotUndefinedAndNotNull(oppPagination.first) + ? oppPagination.first + 1 + : helper.isNotUndefinedAndNotNull(oppPagination.last) + ? oppPagination.last + 1 + : undefined; + + try { + const oppResult = await session.run( + `MATCH (n:<%- nameCp -%>) ${oppFilter} RETURN n ${oppSort} LIMIT ${oppLimit}` + ); + oppNodes = oppResult.records.map( + (res) => new <%- nameLc -%>(res.get(0).properties) + ); + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + + // build the graphql Connection Object + let edges = nodes.map((res) => { + return { + node: res, + cursor: res.base64Enconde(), + }; + }); + const pageInfo = helper.buildPageInfo(edges, oppNodes, pagination); + return { edges, pageInfo, <%- namePl -%>: edges.map((edge) => edge.node) }; + } + + /** + * addOne - The model implementation method for adding a record in Neo4j, based on Neo4j Node driver. + * + * @param {object} input - The input object. + * @return {object} The created record + * @throw {Error} If the process fails, an error is thrown + */ + static async addOne(input) { + // validate input + await validatorUtil.validateData("validateForCreate", this, input); + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + try { + delete input.skipAssociationsExistenceChecks; + input = neo4jHelper.processDateTime(input, definition.attributes); + + const result = await session.run(`CREATE (a:<%- nameCp -%> $props) RETURN a`, { + props: input, + }); + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return new <%- nameLc -%>(node.properties); + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + + /** + * deleteOne - The model implementation for deleting a single record, given by its ID, in Neo4j. + * + * @param {string} id - The ID of the record to be deleted + * @returns {string} A success message is returned + * @throw {Error} If the record could not be deleted - this means a record with the ID is still present + */ + static async deleteOne(id) { + //validate id + await validatorUtil.validateData("validateForDelete", this, id); + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + try { + const result = await session.run( + `MATCH (n:<%- nameCp -%> {${this.idAttribute()}:$id}) DELETE n`, + { id: id } + ); + if (result.records.length !== 0) { + throw new Error(`Record with ID = ${id} has not been deleted!`); + } + return "Item successfully deleted"; + } catch (error) { + console.log(`Record with ID = ${id} could not be deleted`); + throw error; + } finally { + await session.close(); + } + } + + /** + * updateOne - The model implementation for updating a single record in Neo4j. + * + * @param {object} input - The input object. + * @returns {object} The updated record + * @throw {Error} If this method fails, an error is thrown + */ + static async updateOne(input) { + //validate input + await validatorUtil.validateData("validateForUpdate", this, input); + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + const id = input[this.idAttribute()]; + try { + delete input.skipAssociationsExistenceChecks; + delete input[this.idAttribute()]; + input = neo4jHelper.processDateTime(input, definition.attributes); + + const result = await session.run( + `MATCH (n:<%- nameCp -%> {${this.idAttribute()}:$id}) SET n+=$props RETURN n`, + { id: id, props: input } + ); + if (result.records.length !== 1) { + throw new Error(`Record with ID = ${id} has not been updated!`); + } + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return new <%- nameLc -%>(node.properties); + } catch (error) { + console.log(`Record with ID = ${id} could not be updated`); + throw error; + } finally { + await session.close(); + } + } + + /** + * bulkAddCsv - Add records from csv file + * + * @param {object} context - contextual information, e.g. csv file, record delimiter and column names. + */ + static async bulkAddCsv(context) { + let field_delim = config.fieldDelimiter ?? ","; + let array_delim = config.arrayDelimiter ?? ";"; + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + try { + let query = `LOAD CSV WITH HEADERS FROM 'file:///<%- nameLc -%>.csv' AS line FIELDTERMINATOR '${field_delim}' CREATE (:Movie {`; + for (let attr of Object.keys(definition.attributes)) { + let type = definition.attributes[attr].replace(/\s+/g, ""); + if (type[0] === "[") { + type = type.slice(1, type.length - 1); + if (type === "Int") { + query += `${attr}: [i in split(line.${attr}, "${array_delim}") | toInteger(i)], `; + } else if (type === "Boolean") { + query += `${attr}: [i in split(line.${attr}, "${array_delim}") | toBoolean(i)], `; + } else if (type === "Float") { + query += `${attr}: [i in split(line.${attr}, "${array_delim}") | toFloat(i)], `; + } else { + query += `${attr}: split(line.${attr}, "${array_delim}"), `; + } + } else { + if (type === "Int") { + query += `${attr}: toInteger(line.${attr}), `; + } else if (type === "Boolean") { + query += `${attr}: toBoolean(line.${attr}), `; + } else if (type === "Float") { + query += `${attr}: toFloat(line.${attr}), `; + } else { + query += `${attr}: line.${attr}, `; + } + } + } + query = query.slice(0, query.length - 2) + "})"; + const result = await session.run(query); + return `Successfully upload file`; + } catch (e) { + throw new Error(e); + } finally { + await session.close(); + } + } + + /** + * csvTableTemplate - Allows the user to download a template in CSV format with the + * properties and types of this model. + * + * @param {BenignErrorReporter} benignErrorReporter can be used to generate the standard + * GraphQL output {error: ..., data: ...}. If the function reportError of the benignErrorReporter + * is invoked, the server will include any so reported errors in the final response, i.e. the + * GraphQL response will have a non empty errors property. + */ + static async csvTableTemplate(benignErrorReporter) { + return helper.csvTableTemplate(definition); + } + + <%- include('./includes/create-generic-fieldResolvers'); %> + <%- include('./includes/create-models-fieldMutations-neo4j', {op: "add"}); %> + <%- include('./includes/create-models-fieldMutations-neo4j', {op: "remove"}); %> + <%- include('./includes/create-models-fieldMutations-generic-associations', {op: "add"}); %> + <%- include('./includes/create-models-fieldMutations-generic-associations', {op: "remove"}); %> + <%- include('./includes/bulkAssociations-models', {op: "add"}); %> + <%- include('./includes/bulkAssociations-models', {op: "remove"}); %> + + /** + * idAttribute - Check whether an attribute "internalId" is given in the JSON model. If not the standard "id" is used instead. + * + * @return {type} Name of the attribute that functions as an internalId + */ + static idAttribute() { + return <%- nameLc -%>.definition.id.name; + } + + /** + * idAttributeType - Return the Type of the internalId. + * + * @return {type} Type given in the JSON model + */ + static idAttributeType() { + return <%- nameLc -%>.definition.id.type; + } + + /** + * getIdValue - Get the value of the idAttribute ("id", or "internalId") for an instance of movie. + * + * @return {type} id value + */ + getIdValue() { + return this[<%- nameLc -%>.idAttribute()]; + } + + static get definition() { + return definition; + } + + static base64Decode(cursor) { + return Buffer.from(cursor, "base64").toString("utf-8"); + } + + base64Enconde() { + return Buffer.from(JSON.stringify(this.stripAssociations())).toString( + "base64" + ); + } + + stripAssociations(){ + let attributes = Object.keys(<%- nameLc -%>.definition.attributes); + <%if( defaultId ){-%>attributes.push('<%- idAttribute -%>'); <%}-%> + let data_values = _.pick(this, attributes); + return data_values; + } + + static externalIdsArray() { + let externalIds = []; + if (definition.externalIds) { + externalIds = definition.externalIds; + } + + return externalIds; + } + + static externalIdsObject(){ + return { + <%for(let i=0; i < externalIds.length; i++){-%> <%=externalIds[i]-%>: '<%=attributes[ externalIds[i] ]-%>' <%if(i !== (externalIds.length -1) ){ -%>,<%}-%><%}-%> + }; + } +}; diff --git a/views/create-models-trino.ejs b/views/create-models-trino.ejs index c0657d89..b0af287d 100644 --- a/views/create-models-trino.ejs +++ b/views/create-models-trino.ejs @@ -217,7 +217,7 @@ module.exports = class <%- nameLc -%> { ${filter} ${sort} LIMIT ${limit}`; - let result = null; + let result = []; const client = await this.storageHandler; result = await prestoHelper.queryData(query, client); diff --git a/views/create-neo4j-adapter.ejs b/views/create-neo4j-adapter.ejs new file mode 100644 index 00000000..3f8c427f --- /dev/null +++ b/views/create-neo4j-adapter.ejs @@ -0,0 +1,482 @@ +const _ = require("lodash"); +const validatorUtil = require("../../utils/validatorUtil"); +const path = require("path"); +const helper = require("../../utils/helper"); +const neo4jHelper = require("../../utils/neo4j_helper"); +const errorHelper = require("../../utils/errors"); +const neo4j = require("neo4j-driver"); +const config = require("../../config/data_models_storage_config.json")["<%- database -%>"]; +const models = require(path.join(__dirname, "..", "index.js")); + +const remoteZendroURL = "<%- url -%>"; +const iriRegex = new RegExp('<%- regex -%>'); + +// An exact copy of the the model definition that comes from the .json file +const definition = <%- definition -%>; + +/** + * module - Creates a class for Neo4j data model + * + */ + +module.exports = class <%- adapterName -%> { + + constructor(input){ + for (let key of Object.keys(input)) { + this[key] = input[key]; + } + } + + /** + * Get the storage handler, which is a static property of the data model class. + * @returns connected Neo4j client + */ + get storageHandler() { + return <%- adapterName-%>.storageHandler; + } + + static get adapterName(){ + return '<%- adapterName -%>'; + } + + static get adapterType(){ + return '<%- storageType -%>'; + } + + static recognizeId(iri){ + return iriRegex.test(iri); + } + + /** + * readById - The model implementation for reading a single record given by its ID + * + * This method is the implementation for reading a single record for the neo4j storage type, based on neo4j node driver. + * @param {string} id - The ID of the requested record + * @return {object} The requested record as an object with the type <%- nameLc -%>, or an error object if the validation after reading fails + * @throws {Error} If the requested record does not exist + */ + static async readById(id) { + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.READ, + }); + try { + const result = await session.run( + `MATCH (n:<%- nameCp -%> {${this.idAttribute()}:$id}) RETURN n`, + { id: id } + ); + if (result.records.length === 0) { + throw new Error(`Record with ID = "${id}" does not exist`); + } + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return validatorUtil.validateData( + "validateAfterRead", + this, + new <%- adapterName-%>(node.properties) + ); + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + + /** + * countRecords - The model implementation for counting the number of records, possibly restricted by a search term + * + * This method is the implementation for counting the number of records that fulfill a given condition, or for all records in the table, + * for the Neo4j storage type, based on Neo4j node driver. + * @param {object} search - The search term that restricts the set of records to be counted - if undefined, all records in the table + * @param {BenignErrorReporter} benignErrorReporter can be used to generate the standard + * @return {number} The number of records that fulfill the condition, or of all records in the table + */ + static async countRecords(search) { + const whereOptions = neo4jHelper.searchConditionsToNeo4j( + search, + definition + ); + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.READ, + }); + try { + const result = await session.run( + `MATCH (n:<%- nameCp -%>) ${whereOptions} RETURN COUNT(n)` + ); + const singleRecord = result.records[0]; + const num = singleRecord.get(0); + return num; + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + + /** + * readAllCursor - The model implementation for searching for records in Neo4j. This method uses cursor based pagination. + * + * @param {object} search - The search condition for which records shall be fetched + * @param {array} order - Type of sorting (ASC, DESC) for each field + * @param {object} pagination - The parameters for pagination, which can be used to get a subset of the requested record set. + * @param {BenignErrorReporter} benignErrorReporter can be used to generate the standard + * @return {object} The set of records, possibly constrained by pagination, with full cursor information for all records + */ + static async readAllCursor(search, order, pagination, benignErrorReporter) { + //use default BenignErrorReporter if no BenignErrorReporter defined + benignErrorReporter = + errorHelper.getDefaultBenignErrorReporterIfUndef(benignErrorReporter); + let isForwardPagination = helper.isForwardPagination(pagination); + // build the whereOptions. + let filter = neo4jHelper.searchConditionsToNeo4j(search, definition); + let newOrder = isForwardPagination + ? order + : helper.reverseOrderConditions(order); + // depending on the direction build the order object + let sort = neo4jHelper.orderConditionsToNeo4j( + newOrder, + this.idAttribute(), + isForwardPagination + ); + let orderFields = newOrder ? newOrder.map((x) => x.field) : []; + // extend the filter for the given order and cursor + filter = neo4jHelper.cursorPaginationArgumentsToNeo4j( + pagination, + sort, + filter, + orderFields, + this.idAttribute(), + definition.attributes + ); + + // add +1 to the LIMIT to get information about following pages. + let limit = helper.isNotUndefinedAndNotNull(pagination.first) + ? pagination.first + 1 + : helper.isNotUndefinedAndNotNull(pagination.last) + ? pagination.last + 1 + : undefined; + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.READ, + }); + let nodes = []; + try { + const result = await session.run( + `MATCH (n:<%- nameCp -%>) ${filter} RETURN n ${sort} LIMIT ${limit}` + ); + nodes = result.records.map((res) => new <%- adapterName-%>(res.get(0).properties)); + nodes = await validatorUtil.bulkValidateData( + "validateAfterRead", + this, + nodes, + benignErrorReporter + ); + } catch (error) { + throw error; + } + + // get the first record (if exists) in the opposite direction to determine pageInfo. + // if no cursor was given there is no need for an extra query as the results will start at the first (or last) page. + let oppNodes = []; + if (pagination && (pagination.after || pagination.before)) { + // reverse the pagination Arguement. after -> before; set first/last to 0, so LIMIT 1 is executed in the reverse Search + let oppPagination = helper.reversePaginationArgument({ + ...pagination, + includeCursor: false, + }); + let oppForwardPagination = helper.isForwardPagination(oppPagination); + // build the filter object. + let oppFilter = neo4jHelper.searchConditionsToNeo4j(search, definition); + + let oppOrder = oppForwardPagination + ? order + : helper.reverseOrderConditions(order); + // depending on the direction build the order object + let oppSort = neo4jHelper.orderConditionsToNeo4j( + oppOrder, + this.idAttribute(), + oppForwardPagination + ); + let oppOrderFields = oppOrder ? oppOrder.map((x) => x.field) : []; + // extend the filter for the given order and cursor + oppFilter = neo4jHelper.cursorPaginationArgumentsToNeo4j( + oppPagination, + oppSort, + oppFilter, + oppOrderFields, + this.idAttribute(), + definition.attributes + ); + // add +1 to the LIMIT to get information about following pages. + let oppLimit = helper.isNotUndefinedAndNotNull(oppPagination.first) + ? oppPagination.first + 1 + : helper.isNotUndefinedAndNotNull(oppPagination.last) + ? oppPagination.last + 1 + : undefined; + + try { + const oppResult = await session.run( + `MATCH (n:<%- nameCp -%>) ${oppFilter} RETURN n ${oppSort} LIMIT ${oppLimit}` + ); + oppNodes = oppResult.records.map( + (res) => new <%- adapterName-%>(res.get(0).properties) + ); + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + + // build the graphql Connection Object + let edges = nodes.map((res) => { + return { + node: res, + cursor: res.base64Enconde(), + }; + }); + const pageInfo = helper.buildPageInfo(edges, oppNodes, pagination); + return { edges, pageInfo, <%- namePl -%>: edges.map((edge) => edge.node) }; + } + + /** + * addOne - The model implementation method for adding a record in Neo4j, based on Neo4j Node driver. + * + * @param {object} input - The input object. + * @return {object} The created record + * @throw {Error} If the process fails, an error is thrown + */ + static async addOne(input) { + // validate input + await validatorUtil.validateData("validateForCreate", this, input); + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + try { + delete input.skipAssociationsExistenceChecks; + input = neo4jHelper.processDateTime(input, definition.attributes); + + const result = await session.run(`CREATE (a:<%- nameCp -%> $props) RETURN a`, { + props: input, + }); + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return new <%- adapterName-%>(node.properties); + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + + /** + * deleteOne - The model implementation for deleting a single record, given by its ID, in Neo4j. + * + * @param {string} id - The ID of the record to be deleted + * @returns {string} A success message is returned + * @throw {Error} If the record could not be deleted - this means a record with the ID is still present + */ + static async deleteOne(id) { + //validate id + await validatorUtil.validateData("validateForDelete", this, id); + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + try { + const result = await session.run( + `MATCH (n:<%- nameCp -%> {${this.idAttribute()}:$id}) DELETE n`, + { id: id } + ); + if (result.records.length !== 0) { + throw new Error(`Record with ID = ${id} has not been deleted!`); + } + return "Item successfully deleted"; + } catch (error) { + console.log(`Record with ID = ${id} could not be deleted`); + throw error; + } finally { + await session.close(); + } + } + + /** + * updateOne - The model implementation for updating a single record in Neo4j. + * + * @param {object} input - The input object. + * @returns {object} The updated record + * @throw {Error} If this method fails, an error is thrown + */ + static async updateOne(input) { + //validate input + await validatorUtil.validateData("validateForUpdate", this, input); + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + const id = input[this.idAttribute()]; + try { + delete input.skipAssociationsExistenceChecks; + delete input[this.idAttribute()]; + input = neo4jHelper.processDateTime(input, definition.attributes); + + const result = await session.run( + `MATCH (n:<%- nameCp -%> {${this.idAttribute()}:$id}) SET n+=$props RETURN n`, + { id: id, props: input } + ); + if (result.records.length !== 1) { + throw new Error(`Record with ID = ${id} has not been updated!`); + } + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return new <%- adapterName-%>(node.properties); + } catch (error) { + console.log(`Record with ID = ${id} could not be updated`); + throw error; + } finally { + await session.close(); + } + } + + + <%# + /** + * Add and remove methods for to-one association where the foreign key + * is stored in this model and therefore this adapter is the responsible to update the foreign key. + */ + -%> + <%- include('./includes/create-adapter-fields-mutations', {op: "add"}); %> + <%- include('./includes/create-adapter-fields-mutations', {op: "remove"}); %> + + /** + * bulkAddCsv - Add records from csv file + * + * @param {object} context - contextual information, e.g. csv file, record delimiter and column names. + */ + static async bulkAddCsv(context) { + let field_delim = config.fieldDelimiter ?? ","; + let array_delim = config.arrayDelimiter ?? ";"; + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + try { + let query = `LOAD CSV WITH HEADERS FROM 'file:///<%- adapterName-%>.csv' AS line FIELDTERMINATOR '${field_delim}' CREATE (:Movie {`; + for (let attr of Object.keys(definition.attributes)) { + let type = definition.attributes[attr].replace(/\s+/g, ""); + if (type[0] === "[") { + type = type.slice(1, type.length - 1); + if (type === "Int") { + query += `${attr}: [i in split(line.${attr}, "${array_delim}") | toInteger(i)], `; + } else if (type === "Boolean") { + query += `${attr}: [i in split(line.${attr}, "${array_delim}") | toBoolean(i)], `; + } else if (type === "Float") { + query += `${attr}: [i in split(line.${attr}, "${array_delim}") | toFloat(i)], `; + } else { + query += `${attr}: split(line.${attr}, "${array_delim}"), `; + } + } else { + if (type === "Int") { + query += `${attr}: toInteger(line.${attr}), `; + } else if (type === "Boolean") { + query += `${attr}: toBoolean(line.${attr}), `; + } else if (type === "Float") { + query += `${attr}: toFloat(line.${attr}), `; + } else { + query += `${attr}: line.${attr}, `; + } + } + } + query = query.slice(0, query.length - 2) + "})"; + const result = await session.run(query); + return `Successfully upload file`; + } catch (e) { + throw new Error(e); + } finally { + await session.close(); + } + } + + static csvTableTemplate(){ + return helper.csvTableTemplate(definition); + } + + <%- include('./includes/bulkAssociations-models', {op: "add"}); %> + <%- include('./includes/bulkAssociations-models', {op: "remove"}); %> + + /** + * idAttribute - Check whether an attribute "internalId" is given in the JSON model. If not the standard "id" is used instead. + * + * @return {type} Name of the attribute that functions as an internalId + */ + + static idAttribute() { + return <%- adapterName -%>.definition.id.name; + } + + /** + * idAttributeType - Return the Type of the internalId. + * + * @return {type} Type given in the JSON model + */ + + static idAttributeType() { + return <%- adapterName -%>.definition.id.type; + } + + /** + * getIdValue - Get the value of the idAttribute ("id", or "internalId") for an instance of <%- adapterName -%>. + * + * @return {type} id value + */ + + getIdValue() { + return this[<%- adapterName -%>.idAttribute()] + } + + static get definition(){ + return definition; + } + + static base64Decode(cursor){ + return Buffer.from(cursor, 'base64').toString('utf-8'); + } + + base64Enconde(){ + return Buffer.from(JSON.stringify(this.stripAssociations())).toString('base64'); + } + + stripAssociations(){ + let attributes = Object.keys(<%- adapterName -%>.definition.attributes); + <%if( defaultId ){-%>attributes.push('<%- idAttribute -%>'); <%}-%> + let data_values = _.pick(this, attributes); + return data_values; + } + + static externalIdsArray(){ + let externalIds = []; + if(definition.externalIds){ + externalIds = definition.externalIds; + } + + return externalIds; + } + + static externalIdsObject(){ + return { + <%for(let i=0; i < externalIds.length; i++){-%> <%=externalIds[i]-%>: '<%=attributes[ externalIds[i] ]-%>' <%if(i !== (externalIds.length -1) ){ -%>,<%}-%><%}-%> + }; + } + +} diff --git a/views/create-trino-adapter.ejs b/views/create-trino-adapter.ejs index fe10fe86..f5e0ea4a 100644 --- a/views/create-trino-adapter.ejs +++ b/views/create-trino-adapter.ejs @@ -180,7 +180,7 @@ module.exports = class <%- adapterName -%> { ${filter} ${sort} LIMIT ${limit}`; - let result = null; + let result = []; const client = await this.storageHandler; result = await prestoHelper.queryData(query, client); diff --git a/views/includes/bulkAssociations-models.ejs b/views/includes/bulkAssociations-models.ejs index 33444c0c..d820ae16 100644 --- a/views/includes/bulkAssociations-models.ejs +++ b/views/includes/bulkAssociations-models.ejs @@ -94,6 +94,43 @@ return "Records successfully updated!" } <%}_%> + <% if(storageType === 'neo4j' || storageType === 'neo4j-adapter'){_%> + static async bulk<% if(op === 'remove'){%>Dis<%}%>Associate<%-nameCp-%>With<%-associationsArguments["to_one"][i].targetKey_cp-%>(bulkAssociationInput, benignErrorReporter){ + let mappedForeignKeys = helper.mapForeignKeysToPrimaryKeyArray(bulkAssociationInput, "<%-idAttribute%>", "<%-associationsArguments["to_one"][i].targetKey%>"); + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + let foreignKey = `MATCH (n:<%- nameCp -%>) WHERE n.<%-idAttribute%> IN $id + SET n.<%-associationsArguments["to_one"][i].targetKey-%> = $target` + + <% if (op == 'remove') { %>let delete_relationships = `MATCH (a:<%- nameCp -%>)-[r:${"<%-associationsArguments["to_one"][i].name-%>".toUpperCase() + "_EDGE"}]-> (b:<%-associationsArguments["to_one"][i].target_cp-%>) + WHERE a.<%-idAttribute%> IN $id AND b.<%-associationsArguments["to_one"][i].targetKey-%> = $target + DELETE r`<% } + else { %>let create_relationships = `MATCH (a:<%- nameCp -%>), (b:<%-associationsArguments["to_one"][i].target_cp-%>) + WHERE a.<%-idAttribute%> IN $id AND b.<%-associationsArguments["to_one"][i].targetKey-%> = $target + CREATE (a)-[r:${"<%-associationsArguments["to_one"][i].name-%>".toUpperCase() + "_EDGE"}]->(b)`<%}-%> + + try { + for (let { <%-associationsArguments["to_one"][i].targetKey-%>, <%-idAttribute%> } of mappedForeignKeys) { + await session.run(foreignKey, {id: <%-idAttribute%>, target: <% if (op == 'remove') { _%>null<% } else { %><%-associationsArguments["to_one"][i].targetKey-%><%}-%>}) + await session.run(<% if (op == 'remove') { %>delete_relationships<% } else { %>create_relationships<%}-%>, + { + id: <%-idAttribute%>, + target: <%-associationsArguments["to_one"][i].targetKey-%>, + }) + } + } catch (error) { + throw error; + } finally { + await session.close(); + } + + return "Records successfully updated!" + } + <%}_%> <% if(storageType === 'cassandra' || storageType === 'cassandra-adapter'){_%> static async bulk<% if(op === 'remove'){%>Dis<%}%>Associate<%-nameCp-%>With<%-associationsArguments["to_one"][i].targetKey_cp-%>(bulkAssociationInput, benignErrorReporter){ let mappedForeignKeys = helper.mapForeignKeysToPrimaryKeyArray(bulkAssociationInput, "<%-idAttribute%>", "<%-associationsArguments["to_one"][i].targetKey%>"); diff --git a/views/includes/create-adapter-fields-mutations.ejs b/views/includes/create-adapter-fields-mutations.ejs index c1816b2b..42d7d290 100644 --- a/views/includes/create-adapter-fields-mutations.ejs +++ b/views/includes/create-adapter-fields-mutations.ejs @@ -93,6 +93,47 @@ <%}-%> <%# /*** End of the the mongodb-adapter case */ -%> + <%# + /** + * check the type of adapter and handle cassandra-adapter + */ + -%> + <%if(storageType === 'neo4j-adapter'){-%> + static async <%- op -%>_<%-associationsArguments["to_one"][i].targetKey-%>(<%- idAttribute-%>, <%-associationsArguments["to_one"][i].targetKey-%>) { + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + let foreignKey = `MATCH (n:<%- nameCp -%>) WHERE n.<%-idAttribute%> = $id + SET n.<%-associationsArguments["to_one"][i].targetKey-%> = $target RETURN head(collect(n))` + + <% if (op == 'remove') { %>let delete_relationships = `MATCH (a:<%- nameCp -%>)-[r:${"<%-associationsArguments["to_one"][i].name-%>".toUpperCase() + "_EDGE"}]-> (b:<%-associationsArguments["to_one"][i].target_cp-%>) + WHERE a.<%-idAttribute%> = $id AND b.${models.<%-associationsArguments["to_one"][i].target-%>.idAttribute()} = $target + DELETE r`<% } + else { %>let create_relationships = `MATCH (a:<%- nameCp -%>), (b:<%-associationsArguments["to_one"][i].target_cp-%>) + WHERE a.<%-idAttribute%> = $id AND b.${models.<%-associationsArguments["to_one"][i].target-%>.idAttribute()} = $target + CREATE (a)-[r:${"<%-associationsArguments["to_one"][i].name-%>".toUpperCase() + "_EDGE"}]->(b)`<%}-%> + + try{ + const result = await session.run(foreignKey, {id: <%-idAttribute%>, target: <% if (op == 'remove') { _%>null<% } else { %><%-associationsArguments["to_one"][i].targetKey-%><%}-%>}); + await session.run(<% if (op == 'remove') { %>delete_relationships<% } else { %>create_relationships<%}-%>, + { + id: <%-idAttribute%>, + target: <%-associationsArguments["to_one"][i].targetKey-%>, + }) + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return new <%- adapterName -%>(node) + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + <%}-%> + <%# /*** End of the the cassandra-adapter case */ -%> + <%# /** * check the type of adapter and handle cassandra-adapter @@ -168,7 +209,53 @@ } <%}-%> <%# /*** End of the the mongodb-adapter case */ -%> + <%if(storageType === 'neo4j-adapter'){-%> + static async <%- op -%>_<%-associationsArguments["to_many"][i].sourceKey-%>(<%- idAttribute-%>, <%-associationsArguments["to_many"][i].sourceKey-%>, benignErrorReporter, handle_inverse = true) { + //handle inverse association + if(handle_inverse){ + let promises = []; + <%-associationsArguments["to_many"][i].sourceKey-%>.forEach( idx =>{ + promises.push(models.<%-associationsArguments["to_many"][i].target_lc-%>.<%- op %>_<%-associationsArguments["to_many"][i].targetKey%>(idx, [`${<%- idAttribute-%>}`], benignErrorReporter, false) ); + }); + await Promise.all(promises); + } + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + let foreignKey = `MATCH (n:<%- nameCp -%>) WHERE n.<%-idAttribute%> = $id + SET n.<%-associationsArguments["to_many"][i].sourceKey-%> = $updated_ids` + + <% if (op == 'remove') { %>let delete_relationships = `MATCH (a:<%- nameCp -%>)-[r:${"<%-associationsArguments["to_many"][i].name-%>".toUpperCase() + "_EDGE"}]-> (b:<%-associationsArguments["to_many"][i].target_cp-%>) + WHERE a.<%-idAttribute%> = $id AND b.${models.<%-associationsArguments["to_many"][i].target-%>.idAttribute()} IN $source + DELETE r`<% } + else { %>let create_relationships = `MATCH (a:<%- nameCp -%>), (b:<%-associationsArguments["to_many"][i].target_cp-%>) + WHERE a.<%-idAttribute%> = $id AND b.${models.<%-associationsArguments["to_many"][i].target-%>.idAttribute()} IN $source + CREATE (a)-[r:${"<%-associationsArguments["to_many"][i].name-%>".toUpperCase() + "_EDGE"}]->(b)`<%}-%> + + try{ + let record = await this.readById(<%- idAttribute-%>); + + if (record!==null){ + let updated_ids = helper.<% if(op === 'remove'){%>differenceIds<%}else{%>unionIds<%}-%>(record.<%-associationsArguments["to_many"][i].sourceKey-%>, <%-associationsArguments["to_many"][i].sourceKey-%>); + await session.run(foreignKey, {id: <%-idAttribute%>, updated_ids: updated_ids}); + await session.run(<% if (op == 'remove') { %>delete_relationships<% } else { %>create_relationships<%}-%>, + { + id: <%-idAttribute%>, + source: <%-associationsArguments["to_many"][i].sourceKey-%>, + }) + } + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + <%}-%> + <%# /*** End of the the neo4j-adapter case */ -%> <% if(storageType === 'zendro-webservice-adapter' || storageType === 'ddm-adapter'){-%> static async <%- op -%>_<%-associationsArguments["to_many"][i].sourceKey-%>(<%- idAttribute-%>, <%-associationsArguments["to_many"][i].sourceKey-%>, benignErrorReporter) { let query = ` diff --git a/views/includes/create-models-fieldMutations-neo4j.ejs b/views/includes/create-models-fieldMutations-neo4j.ejs new file mode 100644 index 00000000..1379630c --- /dev/null +++ b/views/includes/create-models-fieldMutations-neo4j.ejs @@ -0,0 +1,97 @@ +<%for(let i=0; i < associationsArguments["to_one"].length; i++){-%> + <% if (associationsArguments["to_one"][i].holdsForeignKey) { -%> + /** + * <%- op %>_<%-associationsArguments["to_one"][i].targetKey-%> - field Mutation (model-layer) for to_one associationsArguments to <%- op %> + * + * @param {Id} <%- idAttribute-%> IdAttribute of the root model to be updated + * @param {Id} <%-associationsArguments["to_one"][i].targetKey-%> Foreign Key (stored in "Me") of the Association to be updated. + */ + static async <%- op -%>_<%-associationsArguments["to_one"][i].targetKey-%>(<%- idAttribute-%>, <%-associationsArguments["to_one"][i].targetKey-%>) { + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + let foreignKey = `MATCH (n:<%- nameCp -%> ) WHERE n.<%-idAttribute%> = $id + SET n.<%-associationsArguments["to_one"][i].targetKey-%> = $target RETURN head(collect(n))` + + <% if (op == 'remove') { %>let delete_relationships = `MATCH (a:<%- nameCp -%>)-[r:${"<%-associationsArguments["to_one"][i].name-%>".toUpperCase() + "_EDGE"}]-> (b:<%-associationsArguments["to_one"][i].target_cp-%>) + WHERE a.<%-idAttribute%> = $id AND b.${models.<%-associationsArguments["to_one"][i].target-%>.idAttribute()} = $target + DELETE r`<% } + else { %>let create_relationships = `MATCH (a:<%- nameCp -%>), (b:<%-associationsArguments["to_one"][i].target_cp-%>) + WHERE a.<%-idAttribute%> = $id AND b.${models.<%-associationsArguments["to_one"][i].target-%>.idAttribute()} = $target + CREATE (a)-[r:${"<%-associationsArguments["to_one"][i].name-%>".toUpperCase() + "_EDGE"}]->(b)`<%}-%> + + try{ + const result = await session.run(foreignKey, {id: <%-idAttribute%>, target: <% if (op == 'remove') { _%>null<% } else { %><%-associationsArguments["to_one"][i].targetKey-%><%}-%>}); + await session.run(<% if (op == 'remove') { %>delete_relationships<% } else { %>create_relationships<%}-%>, + { + id: <%-idAttribute%>, + target: <%-associationsArguments["to_one"][i].targetKey-%>, + }) + const singleRecord = result.records[0]; + const node = singleRecord.get(0); + return new <%- name -%>(node) + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + <%} -%> + <%}-%> + + <%for(let i=0; i < associationsArguments["to_many"].length; i++){-%> + <% if (associationsArguments["to_many"][i].assocThroughArray) { -%> + /** + * <%- op %>_<%-associationsArguments["to_many"][i].sourceKey-%> - field Mutation (model-layer) for to_many associationsArguments to <%- op %> + * + * @param {Id} <%- idAttribute-%> IdAttribute of the root model to be updated + * @param {Array} <%-associationsArguments["to_many"][i].sourceKey-%> Array foreign Key (stored in "Me") of the Association to be updated. + */ + static async <%- op -%>_<%-associationsArguments["to_many"][i].sourceKey-%>(<%- idAttribute-%>, <%-associationsArguments["to_many"][i].sourceKey-%>, benignErrorReporter, handle_inverse = true) { + //handle inverse association + if(handle_inverse){ + let promises = []; + <%-associationsArguments["to_many"][i].sourceKey-%>.forEach( idx =>{ + promises.push(models.<%-associationsArguments["to_many"][i].target_lc-%>.<%- op %>_<%-associationsArguments["to_many"][i].targetKey%>(idx, [`${<%- idAttribute-%>}`], benignErrorReporter, false) ); + }); + await Promise.all(promises); + } + + const driver = await this.storageHandler; + const session = driver.session({ + database: config.database, + defaultAccessMode: neo4j.session.WRITE, + }); + let foreignKey = `MATCH (n:<%- nameCp -%> ) WHERE n.<%-idAttribute%> = $id + SET n.<%-associationsArguments["to_many"][i].sourceKey-%> = $updated_ids` + + <% if (op == 'remove') { %>let delete_relationships = `MATCH (a:<%- nameCp -%>)-[r:${"<%-associationsArguments["to_many"][i].name-%>".toUpperCase() + "_EDGE"}]-> (b:<%-associationsArguments["to_many"][i].target_cp-%>) + WHERE a.<%-idAttribute%> = $id AND b.${models.<%-associationsArguments["to_many"][i].target-%>.idAttribute()} IN $source + DELETE r`<% } + else { %>let create_relationships = `MATCH (a:<%- nameCp -%>), (b:<%-associationsArguments["to_many"][i].target_cp-%>) + WHERE a.<%-idAttribute%> = $id AND b.${models.<%-associationsArguments["to_many"][i].target-%>.idAttribute()} IN $source + CREATE (a)-[r:${"<%-associationsArguments["to_many"][i].name-%>".toUpperCase() + "_EDGE"}]->(b)`<%}-%> + + try{ + let record = await this.readById(<%- idAttribute-%>); + + if (record!==null){ + let updated_ids = helper.<% if(op === 'remove'){%>differenceIds<%}else{%>unionIds<%}-%>(record.<%-associationsArguments["to_many"][i].sourceKey-%>, <%-associationsArguments["to_many"][i].sourceKey-%>); + await session.run(foreignKey, {id: <%-idAttribute%>, updated_ids: updated_ids}); + + await session.run(<% if (op == 'remove') { %>delete_relationships<% } else { %>create_relationships<%}-%>, + { + id: <%-idAttribute%>, + source: <%-associationsArguments["to_many"][i].sourceKey-%>, + }) + } + } catch (error) { + throw error; + } finally { + await session.close(); + } + } + <%} -%> + <%}-%> \ No newline at end of file From 5f2135f8eb0219d9237ba4e821f36fd4fb629ac0 Mon Sep 17 00:00:00 2001 From: coeit Date: Thu, 17 Jun 2021 14:51:07 +0200 Subject: [PATCH 13/18] fix: non generic models always have "keysIn" --- funks.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/funks.js b/funks.js index 307fa953..577e34a0 100644 --- a/funks.js +++ b/funks.js @@ -788,9 +788,7 @@ module.exports.parseAssociations = function (dataModel) { // set extra association fields assoc["targetKey"] = association.targetKey; assoc["targetKey_cp"] = capitalizeString(association.targetKey); - if (association.keysIn) { - assoc["keysIn_lc"] = uncapitalizeString(association.keysIn); - } + assoc["keysIn_lc"] = uncapitalizeString(association.keysIn); assoc["holdsForeignKey"] = false; assoc["assocThroughArray"] = false; @@ -1155,6 +1153,7 @@ getStorageType = function (dataModel) { } if (valid) { + console.log(dataModel.model + " -- " + dataModel.storageType.toLowerCase()) return dataModel.storageType.toLowerCase(); } else { return ""; From d869bb90d79743b30b254b1ede5a21c0da9431d4 Mon Sep 17 00:00:00 2001 From: coeit Date: Thu, 17 Jun 2021 14:51:24 +0200 Subject: [PATCH 14/18] fix: missing "to_one" in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c8c76c9b..dd25cb7f 100644 --- a/README.md +++ b/README.md @@ -268,7 +268,7 @@ Example: }, "associations":{ "publisher" : { - "type" : "to_one", // association type + "type" : "many_to_one", // association type "implementation": "foreignkeys", // standard implementation via foreign keys "reverseAssociation": "dogs", // name of the association in the publisher model "target" : "publisher", // Model's name is `publisher` From 5be16c592fa82c153b98dc7deb933c1004892b59 Mon Sep 17 00:00:00 2001 From: coeit Date: Thu, 17 Jun 2021 14:51:44 +0200 Subject: [PATCH 15/18] fix: neo4j test models to new assoc types --- .../actor.json | 6 +++--- .../director.json | 5 +++-- .../dist_director.json | 5 +++-- .../dist_director_instance1.json | 5 +++-- .../dist_movie.json | 5 +++-- .../dist_movie_instance1.json | 5 +++-- .../movie.json | 16 +++++++------- .../review.json | 5 +++-- test/unit_test_misc/data_models_neo4j.js | 21 +++++++++++-------- 9 files changed, 42 insertions(+), 31 deletions(-) diff --git a/test/integration_test_misc/integration_test_models_instance2/actor.json b/test/integration_test_misc/integration_test_models_instance2/actor.json index ab42dfae..ce7fde3c 100644 --- a/test/integration_test_misc/integration_test_models_instance2/actor.json +++ b/test/integration_test_misc/integration_test_models_instance2/actor.json @@ -9,12 +9,12 @@ "associations":{ "movies":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", + "implementation": "foreignkeys", "target": "movie", "targetKey": "actor_ids", "sourceKey": "movie_ids", - "keyIn": "actor", + "keysIn": "actor", "targetStorageType": "neo4j" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/director.json b/test/integration_test_misc/integration_test_models_instance2/director.json index c5a1d2e8..993d63ac 100644 --- a/test/integration_test_misc/integration_test_models_instance2/director.json +++ b/test/integration_test_misc/integration_test_models_instance2/director.json @@ -8,10 +8,11 @@ }, "associations": { "movies": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkeys", "target": "movie", "targetKey": "director_id", - "keyIn": "movie", + "keysIn": "movie", "targetStorageType": "neo4j", "label": "movie_id" } diff --git a/test/integration_test_misc/integration_test_models_instance2/dist_director.json b/test/integration_test_misc/integration_test_models_instance2/dist_director.json index 8654b523..592c47da 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dist_director.json +++ b/test/integration_test_misc/integration_test_models_instance2/dist_director.json @@ -9,10 +9,11 @@ }, "associations": { "dist_movies": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkeys", "target": "dist_movie", "targetKey": "director_id", - "keyIn": "dist_movie", + "keysIn": "dist_movie", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/dist_director_instance1.json b/test/integration_test_misc/integration_test_models_instance2/dist_director_instance1.json index 776f86bd..a5b47120 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dist_director_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance2/dist_director_instance1.json @@ -10,10 +10,11 @@ }, "associations": { "dist_movies": { - "type": "to_many", + "type": "one_to_many", + "implementation": "foreignkeys", "target": "dist_movie", "targetKey": "director_id", - "keyIn": "dist_movie", + "keysIn": "dist_movie", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/dist_movie.json b/test/integration_test_misc/integration_test_models_instance2/dist_movie.json index 3d9a93fa..b0b36f27 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dist_movie.json +++ b/test/integration_test_misc/integration_test_models_instance2/dist_movie.json @@ -15,10 +15,11 @@ "associations": { "dist_director": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkeys", "target": "dist_director", "targetKey": "director_id", - "keyIn" : "dist_movie", + "keysIn" : "dist_movie", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/dist_movie_instance1.json b/test/integration_test_misc/integration_test_models_instance2/dist_movie_instance1.json index 5816349a..8811d324 100644 --- a/test/integration_test_misc/integration_test_models_instance2/dist_movie_instance1.json +++ b/test/integration_test_misc/integration_test_models_instance2/dist_movie_instance1.json @@ -15,10 +15,11 @@ }, "associations": { "dist_director": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkeys", "target": "dist_director", "targetKey": "director_id", - "keyIn": "dist_movie", + "keysIn": "dist_movie", "targetStorageType": "distributed-data-model" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/movie.json b/test/integration_test_misc/integration_test_models_instance2/movie.json index a06dca5d..b76f449a 100644 --- a/test/integration_test_misc/integration_test_models_instance2/movie.json +++ b/test/integration_test_misc/integration_test_models_instance2/movie.json @@ -14,27 +14,29 @@ }, "associations": { "director": { - "type": "to_one", + "type": "many_to_one", + "implementation": "foreignkeys", "target": "director", "targetKey": "director_id", - "keyIn": "movie", + "keysIn": "movie", "targetStorageType": "neo4j", "label": "director_name" }, "actor":{ - "type": "to_many", - "reverseAssociationType": "to_many", + "type": "many_to_many", + "implementation": "foreignkeys", "target": "actor", "targetKey": "movie_ids", "sourceKey": "actor_ids", - "keyIn": "movie", + "keysIn": "movie", "targetStorageType": "neo4j" }, "unique_review":{ - "type" : "to_one", + "type" : "one_to_one", + "implementation": "foreignkeys", "target" : "review", "targetKey" : "movie_id", - "keyIn": "tracker", + "keysIn": "tracker", "targetStorageType" : "neo4j" } }, diff --git a/test/integration_test_misc/integration_test_models_instance2/review.json b/test/integration_test_misc/integration_test_models_instance2/review.json index 2c5006da..16f54086 100644 --- a/test/integration_test_misc/integration_test_models_instance2/review.json +++ b/test/integration_test_misc/integration_test_models_instance2/review.json @@ -8,10 +8,11 @@ }, "associations": { "unique_movie": { - "type" : "to_one", + "type" : "one_to_one", + "implementation": "foreignkeys", "target" : "movie", "targetKey" : "movie_id", - "keyIn": "review", + "keysIn": "review", "targetStorageType" : "neo4j" } }, diff --git a/test/unit_test_misc/data_models_neo4j.js b/test/unit_test_misc/data_models_neo4j.js index 49cc6546..89ed6abe 100644 --- a/test/unit_test_misc/data_models_neo4j.js +++ b/test/unit_test_misc/data_models_neo4j.js @@ -14,27 +14,29 @@ module.exports.movie = { }, associations: { director: { - type: "to_one", + type: "many_to_one", + implementation: "foreignkeys", target: "director", targetKey: "director_id", - keyIn: "movie", + keysIn: "movie", targetStorageType: "neo4j", label: "director_name", }, actor: { - type: "to_many", - reverseAssociationType: "to_many", + type: "one_to_many", + implementation: "foreignkeys", target: "actor", targetKey: "movie_ids", sourceKey: "actor_ids", - keyIn: "movie", + keysIn: "movie", targetStorageType: "neo4j", }, unique_review: { - type: "to_one", + type: "one_to_one", + implementation: "foreignkeys", target: "review", targetKey: "movie_id", - keyIn: "tracker", + keysIn: "tracker", targetStorageType: "neo4j", }, }, @@ -58,10 +60,11 @@ module.exports.dist_movie_instance1 = { }, associations: { dist_director: { - type: "to_one", + type: "many_to_one", + implementation: "foreignkeys", target: "dist_director", targetKey: "director_id", - keyIn: "dist_movie", + keysIn: "dist_movie", targetStorageType: "distributed-data-model", }, }, From 152563f82feafbe3f9a07b16e52e5ffb81fe4cd5 Mon Sep 17 00:00:00 2001 From: coeit Date: Thu, 17 Jun 2021 15:11:53 +0200 Subject: [PATCH 16/18] fix: unit tests --- test/unit_test_misc/data_models_generic_webservice.js | 2 ++ test/unit_test_misc/data_models_neo4j.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/test/unit_test_misc/data_models_generic_webservice.js b/test/unit_test_misc/data_models_generic_webservice.js index 65792cf5..3b3bad7e 100644 --- a/test/unit_test_misc/data_models_generic_webservice.js +++ b/test/unit_test_misc/data_models_generic_webservice.js @@ -23,6 +23,7 @@ module.exports.book = "implementation": "foreignkeys", "target": "Person", "targetKey": "person_id", + "keysIn": "Person", "sourceKey": "book_id", "targetStorageType": "generic" } @@ -47,6 +48,7 @@ module.exports.person = "target": "book", "targetKey": "book_id", "sourceKey": "person_id", + "keysIn": "book", "targetStorageType": "generic" }, diff --git a/test/unit_test_misc/data_models_neo4j.js b/test/unit_test_misc/data_models_neo4j.js index 89ed6abe..1101bc5a 100644 --- a/test/unit_test_misc/data_models_neo4j.js +++ b/test/unit_test_misc/data_models_neo4j.js @@ -23,7 +23,7 @@ module.exports.movie = { label: "director_name", }, actor: { - type: "one_to_many", + type: "many_to_many", implementation: "foreignkeys", target: "actor", targetKey: "movie_ids", From 8770468692d4b9cd6637bd7eb4f9052d56fed213 Mon Sep 17 00:00:00 2001 From: coeit Date: Thu, 17 Jun 2021 15:12:19 +0200 Subject: [PATCH 17/18] chore: remove console.log --- funks.js | 1 - 1 file changed, 1 deletion(-) diff --git a/funks.js b/funks.js index 577e34a0..67e10dbf 100644 --- a/funks.js +++ b/funks.js @@ -1153,7 +1153,6 @@ getStorageType = function (dataModel) { } if (valid) { - console.log(dataModel.model + " -- " + dataModel.storageType.toLowerCase()) return dataModel.storageType.toLowerCase(); } else { return ""; From a619de4397dbcd19380d58b8ff4eda2591f50242 Mon Sep 17 00:00:00 2001 From: coeit Date: Thu, 17 Jun 2021 16:54:48 +0200 Subject: [PATCH 18/18] fix: README many_to_many example assoc type --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dd25cb7f..3444dcfe 100644 --- a/README.md +++ b/README.md @@ -227,7 +227,7 @@ Be aware that in the case of this type of association the user is required to de }, "associations" : { "users" : { - "type" : "to_many", + "type" : "many_to_many", "target" : "User", "implementation": "sql_cross_table", "reverseAssociation": "roles",