--- a/src/main/scala/Main.scala Tue Sep 28 18:23:51 2010 -0400
+++ b/src/main/scala/Main.scala Tue Sep 28 22:54:18 2010 -0400
@@ -122,7 +122,18 @@
KeyMap(m2)
}
}
- type NodeMap = Map[RelName, KeyMap]
+ case class NodeMap(m:Map[RelName, KeyMap]) {
+ def apply(rn:RelName) = m(rn)
+ def ultimateReferent (rn:RelName, k:CandidateKey, vs:List[LexicalValue], db:Database) : Node = {
+ // Issue: what if fk is to a rearrangement of the pk?
+ if (db.m(rn).pk.isDefined && db.m(rn).fks.contains(db.m(rn).pk.get)) {
+ /** Table's primary key is a foreign key. */
+ val target = db.m(rn).fks(db.m(rn).pk.get)
+ ultimateReferent(target.rel, target.attrs, vs, db)
+ } else
+ m(rn)(k)(vs)
+ }
+ }
// Transformation argument:
case class StemIRI(stem:String) {
@@ -131,7 +142,7 @@
// Mapping functions:
def databasemap (u:StemIRI, db:Database) : RDFGraph = {
- val nodes:NodeMap = db.idxables.map(rn => rn -> relation2subject(u, rn, db.m(rn))).toMap
+ val nodes = NodeMap(db.idxables.map(rn => rn -> relation2subject(u, rn, db.m(rn))).toMap)
db.m.keySet.flatMap(rn => relationmap(u, rn, db.m(rn), nodes, db))
}
@@ -147,10 +158,12 @@
val h = header(r)
val s:Node =
if (r.pk.isDefined) {
+ /** Table has a primkary key. */
// Assume: no NULLs in primary key
val vs = r.pk.get.map(k => lexvalue(h, t, k).get)
nodemap(u, rn, r.pk.get, vs)
} else
+ /** Table has no primkary key (but has some candidate keys). */
freshbnode()
(r.candidates.map(k => {
val values:List[CellValue] = k.map(a => t(a))
@@ -163,14 +176,21 @@
def tuplemap (u:StemIRI, rn:RelName, t:Tuple, r:Relation, nodes:NodeMap, db:Database) : Set[Triple] = {
val h = header(r)
+ val hierarchicalKey:List[AttrName] =
+ if (r.pk.isDefined && r.fks.contains(r.pk.get))
+ r.fks(r.pk.get).attrs
+ else
+ List()
+
val s:Node =
if (r.candidates.size > 0) { // which implies !nodes.get(rn).isDefined
// Known to have at least one key, so take the first one.
val k = r.candidates(0)
// Assume: no NULLs in candidate key
val vs = k.map(a => lexvalue(h, t, a).get)
- nodes(rn)(k)(vs)
+ nodes.ultimateReferent(rn, k, vs, db)
} else
+ /** Table has no candidate keys. */
freshbnode()
val allAttrs:Set[AttrName] = h.keySet
@@ -183,11 +203,11 @@
val int:Set[AttrName] = nulllist & a.toSet
if (int.toList.length == 0) None else List(a)
})
- val scalarlist = allAttrs -- unaryFKs -- nulllist /* -- h.pk */
- val referencelist = r.fks.keySet -- nullFKs
+ val scalarlist = allAttrs -- unaryFKs -- nulllist ++ hierarchicalKey
+ val referencelist = r.fks.keySet -- nullFKs - hierarchicalKey
scalarlist.map(a => scalartriples(u, rn, s, a, h, t)) ++
- referencelist.map(as => referencetriples(u, rn, s, as, r, t, nodes, db))
+ referencelist.map(as => referencetriples(u, rn, s, as, r, t, nodes))
}
@@ -204,15 +224,11 @@
val o = literalmap(l, sqlDatatype(h, a))
Triple(s, p, o)
}
- def referencetriples (u:StemIRI, rn:RelName, s:Node, as:List[AttrName], r:Relation, t:Tuple, nodes:NodeMap, db:Database) : Triple = {
+ def referencetriples (u:StemIRI, rn:RelName, s:Node, as:List[AttrName], r:Relation, t:Tuple, nodes:NodeMap) : Triple = {
val p = predicatemap (u, rn, as)
val ls:List[LexicalValue] = as.map(a =>t(a).asInstanceOf[LexicalValue])
val target = r.fks(as)
- val o999 = nodemap(u, target.rel, target.attrs, ls)
val o:Object = nodes(target.rel)(target.attrs)(ls)
- // if (db.m(target.rel).fks.contains(target.attrs))
- // error("need to follow " + target.rel + target.attrs + "->" + db.m(target.rel).fks(target.attrs))
- // println("need to follow " + target.rel + target.attrs)
Triple(s, p, o)
}
--- a/src/test/scala/Test.scala Tue Sep 28 18:23:51 2010 -0400
+++ b/src/test/scala/Test.scala Tue Sep 28 22:54:18 2010 -0400
@@ -294,7 +294,7 @@
val expected:RDFGraph =
Set(
- Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Offices#ID"),TypedLiteral("8",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+ Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Offices#ID"),TypedLiteral("18",IRI("http://www.w3.org/2001/XMLSchema#int"))),
Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Offices#building"),TypedLiteral("32",IRI("http://www.w3.org/2001/XMLSchema#int"))),
Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Offices#ofcNumber"),TypedLiteral("G528",IRI("http://www.w3.org/2001/XMLSchema#string"))),
@@ -306,8 +306,6 @@
Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Addresses#city"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Addresses#state"),TypedLiteral("MA",IRI("http://www.w3.org/2001/XMLSchema#string")))
)
- println("exp:\n " + expected.mkString("\n "))
- println("got:\n " + g.mkString("\n "))
assert (expected === g)
}