Commit cbbde2e7 authored by npedot's avatar npedot
Browse files

adds changeset vsplit decomposition

parent cc26e3ba
Pipeline #7487 failed with stages
in 20 seconds
# vertical specification:
<decompose>
<table tableName>
<cols>
<constraint fun dep>
<source><cols>
<target><cols>
<changeSet>
<xpath name="K">tableName key cols</xpath>
<xpath name="LHS">tableName source fun dep cols</xpath>
<xpath name="RHS">tableName target fun dep cols</xpath>
<xpath name="Rest">tableName other cols=*-K-LHS-RHS</xpath>
<createView tableName1>select K,LHS,Rest from tableName</createView>
<createView tableName2>select LHS,RHS from tableName</createView>
<constraint inclusion>
<source tableName1><col>
<target tableName2><col>
<constraint inclusion>
<source tableName2><col>
<target tableName1><col>
<changeSet>
<compose>
<table tableName1>
<cols>
<table tableName2>
<cols>
<constraint inclusion>
<source tableName1><col>
<target tableName2><col>
<constraint inclusion>
<source tableName2><col>
<target tableName1><col>
<xpath name="K">key cols</xpath>
<xpath name="LHS">source fun dep cols</xpath>
<xpath name="RHS">target fun dep cols</xpath>
<xpath name="Rest">other cols</xpath>
<changeSet>
<createView tableName>select * from tableName1 join tableName2 on inclusion col </createView>
<constraint fun dep>
<source><cols>
<target><cols>
<changeSet>
......@@ -11,4 +11,6 @@ class ChangeSet() {
@JacksonXmlElementWrapper(useWrapping=false)
var createView= ArrayList<CreateView>()
@JacksonXmlElementWrapper(useWrapping=false)
var createConstraint= ArrayList<Constraint>()
}
\ No newline at end of file
......@@ -12,5 +12,5 @@ class CreateView() {
@JacksonXmlProperty(isAttribute = true)
var viewName: String = ""
@JacksonXmlText
var value:String = ""
var text:String = ""
}
\ No newline at end of file
......@@ -6,6 +6,7 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement
@JacksonXmlRootElement(localName = "database")
open class Database () {
@JacksonXmlProperty(isAttribute = true)
var name: String =""
@JacksonXmlProperty(isAttribute = true)
......@@ -19,4 +20,5 @@ open class Database () {
// this.id=id
// this.schema=schema
// }
}
......@@ -16,4 +16,55 @@ class Schema () {
fun table(name: String):Table {
return tables.filter { t -> t.name==name }.first()
}
fun key(tableName: String): Set<Column> {
var resultCols = mutableSetOf<Column>()
val first = constraints.filter { c ->
c.type == Constraint.TYPE.PRIMARY_KEY.name &&
c.name == "primaryKey.${tableName}"
}.toList()
if (first.isEmpty()) return mutableSetOf()
return first[0].source.columns.toSet()
}
fun functionalLHS(tableName: String): Set<Column> {
var resultCols = mutableSetOf<Column>()
val first = constraints.filter { c ->
c.type == Constraint.TYPE.FUNCTIONAL.name &&
c.name == "functional.${tableName}"
}.toList()
if (first.isEmpty()) return mutableSetOf()
return first[0].source.columns.toSet()
}
fun functionalRHS(tableName: String): Set<Column> {
var resultCols = mutableSetOf<Column>()
val first = constraints.filter { c ->
c.type == Constraint.TYPE.FUNCTIONAL.name &&
c.name == "functional.${tableName}"
}.toList()
if (first.isEmpty()) return mutableSetOf()
return first[0].target.columns.toSet()
}
fun key(tableName:String,k:Set<Column>) {
val primaryConstraint = Constraint()
primaryConstraint.name="primaryKey.$tableName"
primaryConstraint.source.table="$tableName"
primaryConstraint.source.columns.addAll(k)
primaryConstraint.type=Constraint.TYPE.PRIMARY_KEY.name
constraints.add(primaryConstraint)
}
fun functional(tableName:String, lhs:Set<Column>, rhs:Set<Column>){
val functionalConstraint = Constraint()
functionalConstraint.name="functional.$tableName"
functionalConstraint.source.table="$tableName"
functionalConstraint.source.columns.addAll(lhs)
functionalConstraint.target.table="$tableName"
functionalConstraint.target.columns.addAll(rhs)
functionalConstraint.type= Constraint.TYPE.FUNCTIONAL.name
constraints.add(functionalConstraint)
}
}
......@@ -10,7 +10,6 @@ class PersonHSplitScenario {
fun run() {
val personMetadata = buildPersonMetadata()
hsplitPersonMetadata(personMetadata)
}
private fun buildPersonMetadata(): Database {
......@@ -27,6 +26,7 @@ class PersonHSplitScenario {
colS.nullable=true
personTable.columns.add(colS)
db.schema.tables.add(personTable)
val primaryConstraint = Constraint()
primaryConstraint.name="primaryKey.person"
primaryConstraint.source.table="person"
......@@ -34,6 +34,7 @@ class PersonHSplitScenario {
primaryConstraint.source.columns.add(colT)
primaryConstraint.type=Constraint.TYPE.PRIMARY_KEY.name
db.schema.constraints.add(primaryConstraint)
return db
}
......
package unibz.cs.semint.kprime.scenario
import unibz.cs.semint.kprime.adapter.service.XMLSerializerJacksonAdapter
import unibz.cs.semint.kprime.domain.*
import unibz.cs.semint.kprime.usecase.XMLSerializeUseCase
class PersonVSplitScenario {
fun run(): ChangeSet {
val personMetadata = buildPersonMetadata()
println(XMLSerializeUseCase(XMLSerializerJacksonAdapter()).prettyDatabase(personMetadata))
return vsplitPersonMetadata(personMetadata)
}
private fun buildPersonMetadata(): Database {
val db = Database()
val personTable = Table()
personTable.name= "person"
val colSSN = Column("SSN", "id.SSN", "dbname.SSN")
personTable.columns.add(colSSN)
colSSN.nullable=false
val colT = Column("T", "id.T", "dbname.T")
personTable.columns.add(colT)
colT.nullable=false
val colS = Column("S", "id.S", "dbname.S")
colS.nullable=true
personTable.columns.add(colS)
val colX = Column("X", "id.X", "dbname.X")
colX.nullable=true
personTable.columns.add(colX)
db.schema.key("person", mutableSetOf(colSSN))
db.schema.functional("person", mutableSetOf(colT), mutableSetOf(colS))
db.schema.tables.add(personTable)
return db
}
private fun vsplitPersonMetadata(personMetadata: Database): ChangeSet {
// check for functional dep
// create changeset
var changeSet = ChangeSet()
// compute K
val keyCols = personMetadata.schema.key("person")
var key = keyCols.map { x -> x.name }.toSet()
println("key $key")
// compute LHS
var lhsCols = personMetadata.schema.functionalLHS("person")
var lhs= lhsCols.map { x -> x.name }.toSet()
println("lhs $lhs")
if (lhs.isEmpty()) return changeSet
// compute RHS
val rhsCols = personMetadata.schema.functionalRHS("person")
var rhs = rhsCols.map { x -> x.name }.toSet()
println("rhs $rhs")
// compute Rest
val allCols = personMetadata.schema.table("person").columns.toSet()
val all = allCols.map { x -> x.name }.toSet()
var rest = all.minus(key).minus(lhs).minus(rhs)
val allNotKey = all.minus(key)
val allNotKeyCols = allCols.minus(keyCols)
println("rest $rest")
// create view1 = select K,LHS,Rest
var view1cols = "select "+key.plus(lhs).plus(rest).joinToString()+" from person"
val view1 = CreateView()
view1.viewName="tableName1"
view1.text=view1cols
changeSet.createView.add(view1)
// create view2 = select LHS,RHS
var view2cols = "select "+lhs.plus(rhs).joinToString()+" from person"
val view2 = CreateView()
view2.viewName="tableName2"
view2.text=view2cols
changeSet.createView.add(view2)
// create inclusion constraint tab1 tab2
val inclusionTab1Tab2 = Constraint()
inclusionTab1Tab2.type=Constraint.TYPE.INCLUSION.name
inclusionTab1Tab2.source.table="tableName1"
inclusionTab1Tab2.source.columns.addAll(lhsCols)
inclusionTab1Tab2.target.table="tableName2"
inclusionTab1Tab2.target.columns.addAll(lhsCols)
changeSet.createConstraint.add(inclusionTab1Tab2)
// create inclusion constraint tab2 tab1
val inclusionTab2Tab1 = Constraint()
inclusionTab2Tab1.type=Constraint.TYPE.INCLUSION.name
inclusionTab2Tab1.source.table="tableName2"
inclusionTab2Tab1.source.columns.addAll(lhsCols)
inclusionTab2Tab1.target.table="tableName1"
inclusionTab2Tab1.target.columns.addAll(lhsCols)
changeSet.createConstraint.add(inclusionTab2Tab1)
// create primary key on tab2
val primaryTab2 = Constraint()
primaryTab2.type=Constraint.TYPE.PRIMARY_KEY.name
primaryTab2.source.table="tableName2"
primaryTab2.source.columns.addAll(lhsCols)
primaryTab2.target.table="tableName2"
primaryTab2.target.columns.addAll(rhsCols)
changeSet.createConstraint.add(primaryTab2)
return changeSet
}
}
\ No newline at end of file
package unibz.cs.semint.kprime.usecase
import unibz.cs.semint.kprime.domain.ChangeSet
import unibz.cs.semint.kprime.domain.Database
class ApplyChangeSetUseCase {
fun apply(db: Database, changeset:ChangeSet):Database {
// TODO for every create* and remove* will do it on a cloned db
return Database()
}
}
\ No newline at end of file
package unibz.cs.semint.kprime.usecase
class HSplitDetectUseCase {}
\ No newline at end of file
import unibz.cs.semint.kprime.domain.ChangeSet
import unibz.cs.semint.kprime.domain.Database
class HSplitDetectUseCase: TransformerUseCase {
override fun compute(db: Database): ChangeSet {
TODO("not implemented")
}
}
\ No newline at end of file
package unibz.cs.semint.kprime.usecase
import unibz.cs.semint.kprime.domain.ChangeSet
import unibz.cs.semint.kprime.domain.Database
interface TransformerUseCase {
fun compute(db: Database):ChangeSet
}
\ No newline at end of file
......@@ -12,7 +12,7 @@ class ChangeSetTest {
// given
val changeSet = ChangeSet()
val view = CreateView()
view.value="select * from table"
view.text="select * from table"
changeSet.createView.add(view)
changeSet.createView.add(view)
// when
......
package unibz.cs.semint.kprime.scenario
import org.junit.Test
import unibz.cs.semint.kprime.adapter.service.XMLSerializerJacksonAdapter
import unibz.cs.semint.kprime.usecase.XMLSerializeUseCase
class PersonVSplitScenarioTI {
@Test
fun test_person_vsplit_scenario() {
// given
val personVSplitScenario = PersonVSplitScenario()
// when
val changeSet = personVSplitScenario.run()
// then
// prints changeset
println(XMLSerializeUseCase(XMLSerializerJacksonAdapter()).prettyChangeSet(changeSet))
}
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment