Skip to content
Snippets Groups Projects
Commit cbbde2e7 authored by npedot's avatar npedot
Browse files

adds changeset vsplit decomposition

parent cc26e3ba
No related branches found
No related tags found
No related merge requests found
Pipeline #7487 failed
Showing
with 253 additions and 4 deletions
# 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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment