/*****************************************************************
* 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
*
* 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.merge;
import org.apache.cayenne.dbsync.merge.builders.DbEntityBuilder;
import org.apache.cayenne.dbsync.merge.factory.HSQLMergerTokenFactory;
import org.apache.cayenne.dbsync.merge.token.MergerToken;
import org.apache.cayenne.dbsync.merge.token.db.SetColumnTypeToDb;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbEntity;
import org.junit.Test;
import java.util.List;
import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dataMap;
import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbAttr;
import static org.apache.cayenne.dbsync.merge.builders.ObjectMother.dbEntity;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class DataMapMergerTest {
@Test
public void testEmptyDataMap() throws Exception {
DataMap existing = dataMap().build();
DataMap db = dataMap().build();
assertEquals(0, dbMerger().createMergeTokens(existing, db).size());
}
@Test
public void testAddTable() throws Exception {
DbEntityBuilder dbEntity =
dbEntity("table1").attributes(
dbAttr("attr01").typeInt()
);
DataMap existing = dataMap().with(dbEntity).build();
DataMap db = dataMap().build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(1, tokens.size());
assertEquals(factory().createCreateTableToDb(dbEntity.build()).getTokenValue(),
tokens.get(0).getTokenValue());
}
@Test
public void testRemoveTable() throws Exception {
DataMap existing = dataMap().build();
DataMap db = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt()
)).build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(1, tokens.size());
assertEquals(factory().createDropTableToDb(db.getDbEntity("table1")).getTokenValue(),
tokens.get(0).getTokenValue());
}
@Test
public void testAddColumn() throws Exception {
DataMap existing = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").typeInt()
)).build();
DataMap db = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt()
)).build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(1, tokens.size());
DbEntity entity = existing.getDbEntity("table1");
assertEquals(factory().createAddColumnToDb(entity, entity.getAttribute("attr02")).getTokenValue(),
tokens.get(0).getTokenValue());
}
@Test
public void testChangeColumnTypeSimple() throws Exception {
DataMap existing = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt()
)).build();
DataMap db = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeVarchar(30)
)).build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(1, tokens.size());
DbEntity entity = existing.getDbEntity("table1");
DbEntity entityDb = db.getDbEntity("table1");
assertTrue(tokens.get(0) instanceof SetColumnTypeToDb);
assertEquals(
factory()
.createSetColumnTypeToDb(entity, entityDb.getAttribute("attr01"), entity.getAttribute("attr01"))
.getTokenValue(),
tokens.get(0)
.getTokenValue()
);
}
@Test
public void testChangeColumnLength() throws Exception {
DataMap existing = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeVarchar(60)
)).build();
DataMap db = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeVarchar(30)
)).build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(1, tokens.size());
DbEntity entity = existing.getDbEntity("table1");
DbEntity entityDb = db.getDbEntity("table1");
assertTrue(tokens.get(0) instanceof SetColumnTypeToDb);
assertEquals(
factory()
.createSetColumnTypeToDb(entity, entityDb.getAttribute("attr01"), entity.getAttribute("attr01"))
.getTokenValue(),
tokens.get(0)
.getTokenValue()
);
}
/**
* Test unsupported type changes
*/
@Test
public void testChangeColumnType() throws Exception {
DbEntity fromModel = dbEntity("table1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").type("DATE"),
dbAttr("attr03").type("BOOLEAN"),
dbAttr("attr04").type("FLOAT")
).build();
DataMap existing = dataMap().with(fromModel).build();
DbEntity fromDb = dbEntity("table1").attributes(
dbAttr("attr01").typeBigInt(),
dbAttr("attr02").type("NUMERIC"),
dbAttr("attr03").type("BLOB"),
dbAttr("attr04").type("TIMESTAMP")
).build();
DataMap db = dataMap().with(fromDb).build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(4, tokens.size());
for(MergerToken token : tokens) {
assertTrue(token instanceof SetColumnTypeToDb);
}
MergerToken attr02Token = findChangeTypeToken(tokens, "attr02");
assertNotNull(attr02Token);
assertEquals(
factory()
.createSetColumnTypeToDb(fromModel, fromDb.getAttribute("attr02"), fromModel.getAttribute("attr02"))
.getTokenValue(),
attr02Token
.getTokenValue()
);
}
private MergerToken findChangeTypeToken(List<MergerToken> tokens, String attributeName) {
for(MergerToken token : tokens) {
if(token.getTokenValue().contains("." + attributeName)) {
return token;
}
}
return null;
}
@Test
public void testDropPrimaryKey() throws Exception {
DataMap existing = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt()
)
).build();
DataMap db = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt().primaryKey()
)
).build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(1, tokens.size());
}
@Test
public void testAddPrimaryKey() throws Exception {
DataMap existing = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt().primaryKey()
)
).build();
DataMap db = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt()
)
).build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(1, tokens.size());
}
@Test
public void testAddRelationship() throws Exception {
DataMap existing = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").typeInt()),
dbEntity("table2").attributes(
dbAttr("attr01").typeInt().primaryKey(),
dbAttr("attr02").typeInt())
).join("rel", "table1.attr01", "table2.attr01")
.build();
DataMap db = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").typeInt()),
dbEntity("table2").attributes(
dbAttr("attr01").typeInt().primaryKey(),
dbAttr("attr02").typeInt())
)//.join("table1.attr01", "table2.attr01")
.build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(1, tokens.size());
DbEntity entity = existing.getDbEntity("table1");
assertEquals(factory().createAddRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(),
tokens.get(0).getTokenValue());
}
@Test
public void testAddRelationship1() throws Exception {
DataMap existing = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").typeInt()),
dbEntity("table2").attributes(
dbAttr("attr01").typeInt().primaryKey(),
dbAttr("attr02").typeInt().primaryKey(),
dbAttr("attr03").typeInt().primaryKey())
).join("rel", "table1.attr01", "table2.attr01")
.join("rel1", "table1.attr01", "table2.attr03")
.build();
DataMap db = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").typeInt()),
dbEntity("table2").attributes(
dbAttr("attr01").typeInt().primaryKey(),
dbAttr("attr02").typeInt().primaryKey(),
dbAttr("attr03").typeInt().primaryKey())
).join("rel", "table1.attr01", "table2.attr02")
.join("rel1", "table1.attr01", "table2.attr03")
.build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(2, tokens.size());
DbEntity entity = existing.getDbEntity("table1");
assertEquals(factory().createDropRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(),
tokens.get(0).getTokenValue());
entity = db.getDbEntity("table1");
assertEquals(factory().createAddRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(),
tokens.get(0).getTokenValue());
}
@Test
public void testTableNameUppercaseRelationship() throws Exception {
DataMap existing = dataMap().with(
dbEntity("TABLE1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").typeInt()),
dbEntity("table2").attributes(
dbAttr("attr01").typeInt().primaryKey(),
dbAttr("attr02").typeInt().primaryKey(),
dbAttr("attr03").typeInt().primaryKey())
).join("rel", "TABLE1.attr01", "table2.attr01").build();
DataMap db = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").typeInt()),
dbEntity("table2").attributes(
dbAttr("attr01").typeInt().primaryKey(),
dbAttr("attr02").typeInt().primaryKey(),
dbAttr("attr03").typeInt().primaryKey())
).join("rel", "table1.attr01", "table2.attr01").build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(0, tokens.size());
}
@Test
public void testAttributeNameUppercaseRelationship() throws Exception {
DataMap existing = dataMap().with(
dbEntity("table1").attributes(
dbAttr("ATTR01").typeInt(),
dbAttr("attr02").typeInt()),
dbEntity("table2").attributes(
dbAttr("attr01").typeInt().primaryKey(),
dbAttr("attr02").typeInt().primaryKey(),
dbAttr("attr03").typeInt().primaryKey())
).join("rel", "table1.ATTR01", "table2.attr01").build();
DataMap db = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").typeInt()),
dbEntity("table2").attributes(
dbAttr("attr01").typeInt().primaryKey(),
dbAttr("attr02").typeInt().primaryKey(),
dbAttr("attr03").typeInt().primaryKey())
).join("rel", "table1.attr01", "table2.attr01").build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(0, tokens.size());
}
@Test
public void testRemoveRelationship() throws Exception {
DataMap existing = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").typeInt()),
dbEntity("table2").attributes(
dbAttr("attr01").typeInt().primaryKey(),
dbAttr("attr02").typeInt())
)
.build();
DataMap db = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").typeInt()),
dbEntity("table2").attributes(
dbAttr("attr01").typeInt().primaryKey(),
dbAttr("attr02").typeInt())
).join("rel", "table1.attr01", "table2.attr01")
.build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(1, tokens.size());
DbEntity entity = db.getDbEntity("table1");
assertEquals(factory().createDropRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(),
tokens.get(0).getTokenValue());
}
@Test
public void testRemoveColumn() throws Exception {
DataMap existing = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt()
)).build();
DataMap db = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").typeInt()
)).build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(1, tokens.size());
DbEntity entity = db.getDbEntity("table1");
assertEquals(factory().createDropColumnToModel(entity, entity.getAttribute("attr02")).getTokenValue(),
tokens.get(0).getTokenValue());
}
@Test
public void testChangeGeneratedStatus() {
DataMap existing = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeVarchar(10)
)).build();
DataMap db = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt().generated()
)).build();
List<MergerToken> tokens = dbMerger().createMergeTokens(existing, db);
assertEquals(2, tokens.size());
}
@Test
public void testNoChanges() throws Exception {
DataMap dataMap1 = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").typeInt(),
dbAttr("attr03").typeInt()
)).build();
DataMap dataMap2 = dataMap().with(
dbEntity("table1").attributes(
dbAttr("attr01").typeInt(),
dbAttr("attr02").typeInt(),
dbAttr("attr03").typeInt()
)).build();
assertEquals(0, dbMerger().createMergeTokens(dataMap1, dataMap2).size());
}
private DataMapMerger dbMerger() {
return DataMapMerger.build(factory());
}
private HSQLMergerTokenFactory factory() {
return new HSQLMergerTokenFactory();
}
}