moved NOT NULL cleaner to the PrettySql object
authorEric Prud'hommeaux <eric@w3.org>
Sat, 09 Jan 2010 00:49:31 -0500
changeset 135 434a54e4588c
parent 134 f661bcdbb2e1
child 136 5aa8c9c0a6e2
moved NOT NULL cleaner to the PrettySql object
src/main/scala/RDB2RDFMain.scala
src/main/scala/SQL.scala
src/test/scala/RDB2RDFTest.scala
--- a/src/main/scala/RDB2RDFMain.scala	Fri Jan 08 19:31:52 2010 -0500
+++ b/src/main/scala/RDB2RDFMain.scala	Sat Jan 09 00:49:31 2010 -0500
@@ -12,6 +12,7 @@
 import scala.util.parsing.combinator._
 import java.net.URI
 import w3c.sw.sql
+import w3c.sw.sql.PrettySql.toPrettySql
 import w3c.sw.sparql
 import w3c.sw.util
 
@@ -248,22 +249,6 @@
     }
   }
 
-  def findNonNullRelAliasAttrs(expr:sql.Expression):Set[sql.RelAliasAttribute] = {
-    expr match {
-      case sql.ExprConjunction(l) => l.foldLeft(Set[sql.RelAliasAttribute]())((s, e) => s ++ findNonNullRelAliasAttrs(e))
-      case sql.ExprDisjunction(l) => l.foldLeft(Set[sql.RelAliasAttribute]())((s, e) => s ++ findNonNullRelAliasAttrs(e))
-      case sql.RelationalExpressionEq(l, r) => findNonNullRelAliasAttrs(l) ++ findNonNullRelAliasAttrs(r)
-      case sql.RelationalExpressionNe(l, r) => findNonNullRelAliasAttrs(l) ++ findNonNullRelAliasAttrs(r)
-      case sql.RelationalExpressionLt(l, r) => findNonNullRelAliasAttrs(l) ++ findNonNullRelAliasAttrs(r)
-      case e:sql.PrimaryExpressionTyped => Set()
-      case sql.PrimaryExpressionAttr(a) => Set(a)
-      case e:sql.ConstNULL => Set()
-      case e:sql.Concat => Set()
-      case sql.RelationalExpressionNull(a) => findNonNullRelAliasAttrs(a)
-      case sql.RelationalExpressionNotNull(a) => findNonNullRelAliasAttrs(a)
-    }
-  }
-
   def varToAttribute(varmap:Map[sparql.Var, SQL2RDFValueMapper], vvar:sparql.Var):sql.RelAliasAttribute = {
     varmap(vvar) match {
       case IntMapper(relalias, disjoints) => relalias
@@ -351,9 +336,7 @@
       case sparql.TriplesBlock(triplepatterns) => {
 	/* Examine each triple, updating the compilation state. */
 	val state2 = triplepatterns.foldLeft(state)((incState,s) => bindOnPredicate(db, incState, s, enforceForeignKeys))
-	val attrAliases = state2.exprs.foldLeft(Set[sql.RelAliasAttribute]())((s, e) => s ++ findNonNullRelAliasAttrs(e))
-	val needNullGuards = findVars(gp).foldLeft(Set[sparql.Var]())((s, v) => if (attrAliases.contains(varToAttribute(state2.varmap, v))) s else s + v)
-	val nullExprs = needNullGuards.foldLeft(Set[sql.Expression]())((s, vvar) => {
+	val nullExprs = findVars(gp).foldLeft(Set[sql.Expression]())((s, vvar) => {
 	  state2.varmap(vvar) match {
 	    case RDFBNoder(relation, relalias, disjoints) => s
 	    case _ => s ++ Set(sql.RelationalExpressionNotNull(sql.PrimaryExpressionAttr(varToAttribute(state2.varmap, vvar))))
@@ -620,6 +603,7 @@
 	case 1 => Some(r2rState.exprs.toList(0))
 	case _ => Some(sql.ExprConjunction(r2rState.exprs))
       }
-    )
+    ).makePretty()
   }
 }
+
--- a/src/main/scala/SQL.scala	Fri Jan 08 19:31:52 2010 -0500
+++ b/src/main/scala/SQL.scala	Sat Jan 09 00:49:31 2010 -0500
@@ -281,3 +281,75 @@
 
 }
 
+case class PrettySql(select:Select) {
+  def makePretty():Select = {
+    val Select(attributelist, tablelist, expression) = select
+    val nullStripped =
+      if (expression.isDefined) {
+	val nonNullAttrs = PrettySql.findNonNullRelAliasAttrs(expression.get)
+	PrettySql.stripNotNulls(expression.get, nonNullAttrs)
+      }
+      else None
+    val strippedTables = tablelist.joins.foldLeft(AddOrderedSet[Join]())((set, join) => set + {
+      join match {
+	case InnerJoin(AliasedResource(rel, as)) => InnerJoin(AliasedResource({ rel match {
+	  case Subselect(s:Select) => Subselect(PrettySql(s).makePretty())
+	  case Subselect(Union(disjoints)) => Subselect(Union(disjoints.map(s => PrettySql(s).makePretty())))
+	  case r:Relation => r
+	}}, as))
+	case LeftOuterJoin(AliasedResource(rel, as), on:Expression) => LeftOuterJoin(AliasedResource({ rel match {
+	  case Subselect(s:Select) => Subselect(PrettySql(s).makePretty())
+	  case Subselect(Union(disjoints)) => Subselect(Union(disjoints.map(s => PrettySql(s).makePretty())))
+	  case r:Relation => r
+	}}, as), on)
+      }})
+    Select(attributelist, TableList(strippedTables), nullStripped)
+  }
+}
+
+object PrettySql {
+  def findNonNullRelAliasAttrs(expr:Expression):Set[RelAliasAttribute] = {
+    expr match {
+      case ExprConjunction(s) => s.foldLeft(Set[RelAliasAttribute]())((s, e) => s ++ findNonNullRelAliasAttrs(e))
+      case ExprDisjunction(s) => {
+	val l = s.toList
+	l.slice(1, l.size).foldLeft(findNonNullRelAliasAttrs(l(0)))((s, e) => s & findNonNullRelAliasAttrs(e))
+      }
+      case RelationalExpressionEq(l, r) => findNonNullRelAliasAttrs(l) ++ findNonNullRelAliasAttrs(r)
+      case RelationalExpressionNe(l, r) => findNonNullRelAliasAttrs(l) ++ findNonNullRelAliasAttrs(r)
+      case RelationalExpressionLt(l, r) => findNonNullRelAliasAttrs(l) ++ findNonNullRelAliasAttrs(r)
+      case e:PrimaryExpressionTyped => Set()
+      case PrimaryExpressionAttr(a) => Set(a)
+      case e:ConstNULL => Set()
+      case e:Concat => Set()
+      case RelationalExpressionNull(a) => findNonNullRelAliasAttrs(a)
+      case RelationalExpressionNotNull(a) => Set()
+    }
+  }
+  def stripNotNulls(expr:Expression, stripMe:Set[RelAliasAttribute]):Option[Expression] = {
+    expr match {
+      case ExprConjunction(l) => Some(ExprConjunction({l.foldLeft(Set[Expression]())((s, e) => {
+	val e2 = stripNotNulls(e,stripMe)
+	if (e2.isDefined) s + e2.get
+	else s})}))
+      case ExprDisjunction(l) => Some(ExprDisjunction({l.foldLeft(Set[Expression]())((s, e) => {
+	val e2 = stripNotNulls(e,stripMe)
+	if (e2.isDefined) s + e2.get
+	else s})}))
+      case e:RelationalExpressionEq => Some(e)
+      case e:RelationalExpressionNe => Some(e)
+      case e:RelationalExpressionLt => Some(e)
+      case e:PrimaryExpressionTyped => Some(e)
+      case e:PrimaryExpressionAttr => Some(e)
+      case e:ConstNULL => Some(e)
+      case e:Concat => Some(e)
+      case e:RelationalExpressionNull => Some(e)
+      case RelationalExpressionNotNull(PrimaryExpressionAttr(a)) =>
+	if (stripMe.contains(a)) None
+	else Some(RelationalExpressionNotNull(PrimaryExpressionAttr(a)))
+      case e:RelationalExpressionNotNull => Some(e)
+    }
+  }
+  implicit def toPrettySql(select:Select) = PrettySql(select)
+}
+
--- a/src/test/scala/RDB2RDFTest.scala	Fri Jan 08 19:31:52 2010 -0500
+++ b/src/test/scala/RDB2RDFTest.scala	Sat Jan 09 00:49:31 2010 -0500
@@ -280,7 +280,6 @@
        INNER JOIN Employee AS R_who ON R_who.empid=R_task1.employee
        INNER JOIN TaskAssignments AS R_task2 ON R_who.empid=R_task2.employee
  WHERE R_task1.id<R_task2.id 
-   AND R_task1.id IS NOT NULL AND R_task2.id IS NOT NULL
 """).get
     val generated = RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), true, false)
     assert(generated === parsed)
@@ -446,9 +445,7 @@
        INNER JOIN Tasks AS R_utask ON R_utask.taskid=R_upper.task
        INNER JOIN Employee AS R_grandManager ON R_grandManager.empid=R_utask.lead
  WHERE R_taskLead.birthday<R_emp.birthday AND R_grandManager.birthday<R_taskLead.birthday
-   AND R_grandManager.birthday IS NOT NULL AND R_emp.lastName IS NOT NULL
-   AND R_emp.birthday IS NOT NULL AND R_grandManager.lastName IS NOT NULL
-   AND R_taskLead.birthday IS NOT NULL AND R_lower.id IS NOT NULL AND R_upper.id IS NOT NULL
+   AND R_emp.lastName IS NOT NULL AND R_grandManager.lastName IS NOT NULL AND R_lower.id IS NOT NULL AND R_upper.id IS NOT NULL
 """).get
     val generated = RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), true, false)
     assert(generated === parsed)
@@ -578,7 +575,8 @@
    AND (G_union0._DISJOINT_!=1 OR R_who.birthday=G_union0.bday)
    AND (G_union0._DISJOINT_!=1 OR R_who.empid=G_union0.who)
    AND R_who.lastName="Smith"
-""").get
+   AND (G_union0.bday IS NOT NULL) AND (G_union0.who IS NOT NULL)
+""").get // !!!    AND (G_union0.bday IS NOT NULL) AND (G_union0.who IS NOT NULL)
     val generated = RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), false, false)
     assert(generated === parsed)
     val output = """
@@ -692,6 +690,7 @@
    AND (G_union1._DISJOINT_!=1 OR G_union1.who=R_who.empid)
    AND (G_union1._DISJOINT_!=1 OR R_who.birthday=G_union1.bday)
    AND R_who.empid IS NOT NULL AND R_who.lastName="Smith"
+   AND (G_union1.bday IS NOT NULL)
 """).get
     val generated = RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), false, false)
     assert(generated === parsed)
@@ -753,7 +752,7 @@
                   ) AS G_opt1 ON 1=1
        INNER JOIN Employee AS R_emp
  WHERE (G_opt1._DISJOINT_ IS NULL OR R_emp.empid=G_opt1.emp)
-   AND R_emp.lastName IS NOT NULL
+   AND R_emp.lastName IS NOT NULL AND G_opt1.emp IS NOT NULL
 """).get
     val generated = RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), false, false)
     assert(generated === parsed)
@@ -834,10 +833,10 @@
        INNER JOIN Employee AS R_emp4
  WHERE (G_opt1._DISJOINT_ IS NULL OR R_emp3.birthday=G_opt1.birthday)
    AND (G_opt1._DISJOINT_ IS NULL OR R_emp4.birthday=G_opt1.birthday)
-   AND R_emp1.empid IS NOT NULL AND R_emp1.lastName IS NOT NULL AND R_emp1.lastName<R_emp2.lastName
-   AND R_emp2.empid IS NOT NULL AND R_emp2.lastName IS NOT NULL AND R_emp2.lastName<R_emp3.lastName
-   AND R_emp3.empid IS NOT NULL AND R_emp3.lastName IS NOT NULL AND R_emp3.lastName<R_emp4.lastName
-   AND R_emp4.empid IS NOT NULL AND R_emp4.lastName IS NOT NULL
+   AND G_opt1.birthday IS NOT NULL AND R_emp1.empid IS NOT NULL AND R_emp1.lastName<R_emp2.lastName
+   AND R_emp2.empid IS NOT NULL AND R_emp2.lastName<R_emp3.lastName
+   AND R_emp3.empid IS NOT NULL AND R_emp3.lastName<R_emp4.lastName
+   AND R_emp4.empid IS NOT NULL
 """).get
     val generated = RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), false, false)
     assert(generated === parsed)