Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CAY-2241 cdbimport: set ObjRelationship delete rule from FK metadata #276

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Date:
----------------------------------
Changes/New Features:

CAY-2241 cdbimport: set ObjRelationship delete rule from FK metadata
CAY-2334 cgen: option to force run from maven/gradle
CAY-2372 Extract new modules from cayenne-server
CAY-2377 Cleanup deprecated code.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.apache.cayenne.dbsync.filter.NameFilter;
import org.apache.cayenne.dbsync.naming.NameBuilder;
import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
import org.apache.cayenne.dbsync.reverse.dbload.DbRelationshipDetected;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
Expand Down Expand Up @@ -194,6 +195,9 @@ private boolean addMissingRelationships(ObjEntity entity) {

private boolean createObjRelationship(ObjEntity entity, DbRelationship dr, String targetEntityName) {
ObjRelationship or = new ObjRelationship();
if (dr instanceof DbRelationshipDetected) {
or.setDeleteRule(((DbRelationshipDetected) dr).getDeleteRule());
}
or.setName(NameBuilder.builder(or, entity)
.baseName(nameGenerator.relationshipName(dr))
.name());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import org.apache.cayenne.dbsync.naming.NameBuilder;
import org.apache.cayenne.dbsync.naming.ObjectNameGenerator;
import org.apache.cayenne.dbsync.reverse.dbload.DbRelationshipDetected;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.ObjRelationship;
Expand Down Expand Up @@ -93,9 +94,9 @@ private boolean isManyToMany() {
}

private void addFlattenedRelationship(ObjectNameGenerator nameGenerator, ObjEntity srcEntity, ObjEntity dstEntity,
DbRelationship rel1, DbRelationship rel2) {
DbRelationship reverseRelationship, DbRelationship dbRelationship) {

if (rel1.getSourceAttributes().isEmpty() && rel2.getTargetAttributes().isEmpty()) {
if (reverseRelationship.getSourceAttributes().isEmpty() && dbRelationship.getTargetAttributes().isEmpty()) {
LOG.warn("Wrong call ManyToManyCandidateEntity.addFlattenedRelationship(... , " + srcEntity.getName()
+ ", " + dstEntity.getName() + ", ...)");

Expand All @@ -105,14 +106,17 @@ private void addFlattenedRelationship(ObjectNameGenerator nameGenerator, ObjEnti
ObjRelationship newRelationship = new ObjRelationship();
newRelationship.setName(NameBuilder
.builder(newRelationship, srcEntity)
.baseName(nameGenerator.relationshipName(rel1, rel2))
.baseName(nameGenerator.relationshipName(reverseRelationship, dbRelationship))
.name());

newRelationship.setSourceEntity(srcEntity);
newRelationship.setTargetEntityName(dstEntity);
if (dbRelationship instanceof DbRelationshipDetected) {
newRelationship.setDeleteRule(((DbRelationshipDetected) dbRelationship).getDeleteRule());
}

newRelationship.addDbRelationship(rel1);
newRelationship.addDbRelationship(rel2);
newRelationship.addDbRelationship(reverseRelationship);
newRelationship.addDbRelationship(dbRelationship);

srcEntity.addRelationship(newRelationship);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
public class DbRelationshipDetected extends DbRelationship {

private String fkName;
private int deleteRule;

public DbRelationshipDetected(String uniqueRelName) {
super(uniqueRelName);
Expand All @@ -51,4 +52,11 @@ void setFkName(String fkName) {
this.fkName = fkName;
}

public int getDeleteRule() {
return deleteRule;
}

public void setDeleteRule(int deleteRule) {
this.deleteRule = deleteRule;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@

package org.apache.cayenne.dbsync.reverse.dbload;

import org.apache.cayenne.map.DeleteRule;
import org.apache.cayenne.util.EqualsBuilder;
import org.apache.cayenne.util.HashCodeBuilder;
import org.apache.cayenne.util.CompareToBuilder;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;

Expand All @@ -36,6 +38,7 @@ public class ExportedKey implements Comparable {

private final KeyData pk;
private final KeyData fk;
private int deleteRule;
private final short keySeq;

/**
Expand All @@ -46,6 +49,11 @@ public class ExportedKey implements Comparable {
* DataBaseMetaData.getExportedKeys(...)
*/
ExportedKey(ResultSet rs) throws SQLException {
try {
deleteRule = translateDbRuleToCayenneRule(Integer.parseInt(rs.getString("DELETE_RULE")));
} catch (Exception exception) {
deleteRule = DeleteRule.NO_ACTION;
}
String pkCatalog = rs.getString("PKTABLE_CAT");
String pkSchema = rs.getString("PKTABLE_SCHEM");
String pkTable = rs.getString("PKTABLE_NAME");
Expand All @@ -63,6 +71,21 @@ public class ExportedKey implements Comparable {
this.keySeq = rs.getShort("KEY_SEQ");
}

private int translateDbRuleToCayenneRule(int deleteRule) {
switch (deleteRule) {
case DatabaseMetaData.importedKeyCascade:
return DeleteRule.CASCADE;
case DatabaseMetaData.importedKeyRestrict:
return DeleteRule.DENY;
case DatabaseMetaData.importedKeySetNull:
return DeleteRule.NULLIFY;
case DatabaseMetaData.importedKeyNoAction:
case DatabaseMetaData.importedKeySetDefault:
default:
return DeleteRule.NO_ACTION;
}
}

public KeyData getPk() {
return pk;
}
Expand All @@ -71,6 +94,10 @@ public KeyData getFk() {
return fk;
}

public int getDeleteRule() {
return deleteRule;
}

@Override
public boolean equals(Object obj) {
if (obj == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ public void load(DatabaseMetaData metaData, DbLoadDataStore map) throws SQLExcep

// forwardRelationship is a reference from table with primary key
// it is what exactly we load from db
DbRelationship forwardRelationship = new DbRelationship();
DbRelationshipDetected forwardRelationship = new DbRelationshipDetected();
forwardRelationship.setSourceEntity(pkEntity);
forwardRelationship.setTargetEntityName(fkEntity);
forwardRelationship.setDeleteRule(key.getDeleteRule());

// TODO: dirty and non-transparent... using DbRelationshipDetected for the benefit of the merge package.
// This info is available from joins....
Expand All @@ -97,6 +98,7 @@ public void load(DatabaseMetaData metaData, DbLoadDataStore map) throws SQLExcep
reverseRelationship.setSourceEntity(fkEntity);
reverseRelationship.setTargetEntityName(pkEntity);
reverseRelationship.setToMany(false);
reverseRelationship.setDeleteRule(key.getDeleteRule());

createAndAppendJoins(exportedKeys, pkEntity, fkEntity, forwardRelationship, reverseRelationship);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public void testMerging() {
assertNotNull(objEntity1.getRelationship("newTable2s"));
assertNotNull(objEntity2.getRelationship("newTable"));

assertEquals(objEntity1.getRelationship("newTable2s").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_MANY);
assertEquals(objEntity1.getRelationship("newTable2s").getDeleteRule(), DeleteRule.NO_ACTION);
assertEquals(objEntity2.getRelationship("newTable").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_ONE);

map.removeObjEntity(objEntity2.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
import org.apache.cayenne.configuration.DataMapLoader;
import org.apache.cayenne.configuration.DataNodeDescriptor;
import org.apache.cayenne.configuration.server.DataSourceFactory;
import org.apache.cayenne.configuration.server.DbAdapterFactory;
import org.apache.cayenne.dba.DbAdapter;
Expand Down Expand Up @@ -49,7 +48,6 @@
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.project.FileProjectSaver;
import org.apache.cayenne.project.Project;
import org.apache.cayenne.project.extension.ProjectExtension;
import org.apache.cayenne.resource.Resource;
import org.apache.cayenne.resource.URLResource;
import org.apache.cayenne.util.Util;
Expand Down Expand Up @@ -180,7 +178,7 @@ public DataMap load() throws SQLException {

final boolean[] haveWeTriedToSave = {false};
DefaultDbImportAction action = buildDbImportAction(
new FileProjectSaver(Collections.<ProjectExtension>emptyList()) {
new FileProjectSaver(Collections.emptyList()) {
@Override
public void save(Project project) {
haveWeTriedToSave[0] = true;
Expand Down Expand Up @@ -292,14 +290,14 @@ private DefaultDbImportAction buildDbImportAction(FileProjectSaver projectSaver,
DbAdapter dbAdapter = mock(DbAdapter.class);

DbAdapterFactory adapterFactory = mock(DbAdapterFactory.class);
when(adapterFactory.createAdapter((DataNodeDescriptor)any(), (DataSource)any())).thenReturn(dbAdapter);
when(adapterFactory.createAdapter(any(), any())).thenReturn(dbAdapter);

DataSourceFactory dataSourceFactory = mock(DataSourceFactory.class);
DataSource mock = mock(DataSource.class);
when(dataSourceFactory.getDataSource((DataNodeDescriptor)any())).thenReturn(mock);
when(dataSourceFactory.getDataSource(any())).thenReturn(mock);

MergerTokenFactoryProvider mergerTokenFactoryProvider = mock(MergerTokenFactoryProvider.class);
when(mergerTokenFactoryProvider.get((DbAdapter)any())).thenReturn(new DefaultMergerTokenFactory());
when(mergerTokenFactoryProvider.get(any())).thenReturn(new DefaultMergerTokenFactory());

DataChannelDescriptorLoader dataChannelDescriptorLoader = mock(DataChannelDescriptorLoader.class);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
/*****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
****************************************************************/

package org.apache.cayenne.dbsync.reverse.dbload;

Expand Down Expand Up @@ -61,6 +61,7 @@ public void testEqualsExportedKey() throws SQLException {
when(rs1.getString("FK_NAME")).thenReturn("FKName");

when(rs1.getShort("KEY_SEQ")).thenReturn((short) 1);
when(rs1.getString("DELETE_RULE")).thenReturn("3");

ExportedKey keyData1 = new ExportedKey(rs1);

Expand All @@ -78,6 +79,7 @@ public void testEqualsExportedKey() throws SQLException {
when(rs2.getString("FK_NAME")).thenReturn("FKName");

when(rs2.getShort("KEY_SEQ")).thenReturn((short)1);
when(rs2.getString("DELETE_RULE")).thenReturn("3");

ExportedKey keyData2 = new ExportedKey(rs2);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,39 @@

import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.DeleteRule;
import org.junit.Ignore;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

public class RelationshipsLoaderIT extends BaseLoaderIT {

// This test ignored because test db is being created with default delete_rules
// and on every databases have different default delete_rules
@Ignore
@Test
public void testRelationshipDeleteRuleLoad() throws Exception {
DatabaseMetaData metaData = connection.getMetaData();
DbLoaderDelegate delegate = new DefaultDbLoaderDelegate();
EntityLoader entityLoader = new EntityLoader(adapter, EMPTY_CONFIG, delegate);
AttributeLoader attributeLoader = new AttributeLoader(adapter, EMPTY_CONFIG, delegate);
ExportedKeyLoader exportedKeyLoader = new ExportedKeyLoader(EMPTY_CONFIG, delegate);

entityLoader.load(metaData, store);
attributeLoader.load(metaData, store);
exportedKeyLoader.load(metaData, store);
RelationshipLoader relationshipLoader = new RelationshipLoader(EMPTY_CONFIG, delegate, new DefaultObjectNameGenerator());
relationshipLoader.load(metaData, store);

DbRelationship relationship = getDbEntity("DELETE_RULE").getRelationship("deleteCascades");
assertEquals(DbRelationshipDetected.class, relationship.getClass());
assertEquals(DeleteRule.CASCADE, ((DbRelationshipDetected) relationship).getDeleteRule());
}

@Test
public void testRelationshipLoad() throws Exception {
boolean supportsFK = accessStackAdapter.supportsFKConstraints();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,17 @@ public static void updateObjEntity(ObjEntity e) {
/**
* Updates delete rules for specified relationship
*/
public static void updateObjRelationship(ObjRelationship rel) {
rel.setDeleteRule(rel.isToMany() ? DeleteRule.DEFAULT_DELETE_RULE_TO_MANY :
DeleteRule.DEFAULT_DELETE_RULE_TO_ONE);
public static void updateObjRelationship(ObjRelationship relationship) {
if (!relationship.isToMany()) {
relationship.setDeleteRule(DeleteRule.DEFAULT_DELETE_RULE_TO_ONE);
}
}

public void objAttributeAdded(ObjAttribute attr) {
}

public void objRelationshipAdded(ObjRelationship rel) {
updateObjRelationship(rel);
public void objRelationshipAdded(ObjRelationship relationship) {
updateObjRelationship(relationship);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ public interface EntityMergeListener {
/**
* Invoked when a missing attribute in ObjEntity is completed from DbEntity
*/
public void objAttributeAdded(ObjAttribute attr);
void objAttributeAdded(ObjAttribute attr);

/**
* Invoked when a missing relationship in ObjEntity is completed from DbEntity
*/
public void objRelationshipAdded(ObjRelationship rel);
void objRelationshipAdded(ObjRelationship relationship);
}
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,11 @@ public void testAddedFlattenedRelationship() throws Exception {
test("testAddedFlattenedRelationship");
}

@Test
public void testImportRelationshipWithDeleteRule() throws Exception {
test("testImportRelationshipWithDeleteRule");
}

@Test
public void testFilteringConfig() throws Exception {
DbImporterMojo cdbImport = getCdbImport("config/pom-01.xml");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@


<obj-relationship name="parent" source="Child" target="Parent" deleteRule="Nullify" db-relationship-path="parent"/>
<obj-relationship name="children" source="Parent" target="Child" deleteRule="Deny" db-relationship-path="children"/>
<obj-relationship name="children" source="Parent" target="Child" db-relationship-path="children"/>
</data-map>

Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
<db-relationship name="address" source="CHILD" target="ADDRESS">
<db-attribute-pair source="ADDRESS_ID" target="id"/>
</db-relationship>
<obj-relationship name="children" source="Address" target="Child" deleteRule="Deny" db-relationship-path="children"/>
<obj-relationship name="children" source="Address" target="Child" db-relationship-path="children"/>
<obj-relationship name="address" source="Child" target="Address" deleteRule="Nullify" db-relationship-path="address"/>

</data-map>
Loading