~ merge
authorAlexandre Bertails <alexandre@bertails.org>
Sun, 13 Jun 2010 19:32:44 -0400
changeset 218 7a169dfe5368
parent 217 af32394cf372 (current diff)
parent 214 32e8f17bf5ce (diff)
child 219 5716b5311aa7
~ merge
--- a/src/main/scala/SPARQL.scala	Sun Jun 13 19:31:21 2010 -0400
+++ b/src/main/scala/SPARQL.scala	Sun Jun 13 19:32:44 2010 -0400
@@ -18,15 +18,16 @@
 
 case class Select(distinct:Boolean, attrs:SparqlAttributeList, gp:GraphPattern, order:List[OrderElt], offset:Option[Int], limit:Option[Int]) {
   override def toString =
+    "SELECT "+
     { if (distinct) "DISTINCT " else "" }+
-    attrs+"\n"+gp+
-    { if (order.size > 0) { "ORDER BY " + order.map(o => o.toString).mkString(" ") } else "" }+
-    { if (offset.isDefined) {"OFFSET " + offset } else "" }+
-    { if (limit.isDefined) {"LIMIT " + limit } else "" }
+    attrs+"\n"+gp+" "+
+    { if (order.size > 0) {order.map(o => o.toString).mkString("ORDER BY ", " ", " ") } else "" }+
+    { if (offset.isDefined) {"OFFSET " + offset + " "} else "" }+
+    { if (limit.isDefined) {"LIMIT " + limit + " "} else "" }
 }
 case class Construct(head:TriplesBlock, gp:GraphPattern)
 case class SparqlAttributeList(attributelist:List[Var]) {
-  override def toString = "SELECT "+(attributelist.toList.sortWith((l, r) => l.s < r.s).mkString(" "))
+  override def toString = attributelist.toList.sortWith((l, r) => l.s < r.s).mkString(" ")
 }
 
 sealed abstract class GraphPattern {
@@ -224,12 +225,23 @@
   override def toString = "_:" + s
 }
 
-case class Expression(conjuncts:List[PrimaryExpression])
+case class Expression(conjuncts:List[PrimaryExpression]) {
+  override def toString = conjuncts.map(e => e.toString()).mkString(" && ")
+}
+
 sealed abstract class PrimaryExpression
-case class PrimaryExpressionEq(left:SparqlTermExpression, right:SparqlTermExpression) extends PrimaryExpression
-case class PrimaryExpressionLt(left:SparqlTermExpression, right:SparqlTermExpression) extends PrimaryExpression
-case class PrimaryExpressionGt(left:SparqlTermExpression, right:SparqlTermExpression) extends PrimaryExpression
-case class SparqlTermExpression(term:Term) extends PrimaryExpression
+case class PrimaryExpressionEq(left:SparqlTermExpression, right:SparqlTermExpression) extends PrimaryExpression {
+  override def toString = left.toString() + " = " + right.toString
+}
+case class PrimaryExpressionLt(left:SparqlTermExpression, right:SparqlTermExpression) extends PrimaryExpression {
+  override def toString = left.toString() + " < " + right.toString
+}
+case class PrimaryExpressionGt(left:SparqlTermExpression, right:SparqlTermExpression) extends PrimaryExpression {
+  override def toString = left.toString() + " > " + right.toString
+}
+case class SparqlTermExpression(term:Term) extends PrimaryExpression {
+  override def toString = term.toString
+}
 
 case class OrderElt(desc:Boolean, expr:Expression) {
   override def toString = { if (desc) "DESC" else "ASC" } + "(" + expr.toString + ")"
--- a/src/main/scala/SQL.scala	Sun Jun 13 19:31:21 2010 -0400
+++ b/src/main/scala/SQL.scala	Sun Jun 13 19:32:44 2010 -0400
@@ -19,11 +19,16 @@
   override def toString = "(\n       " + sel.toString.replace("\n", "\n       ") + "\n                  )"
 }
 sealed abstract class SelectORUnion
-case class Select(attributelist:AttributeList, tablelist:TableList, expression:Option[Expression]) extends SelectORUnion {
-  override def toString = expression match {
-    case Some(expr) => attributelist+"\n"+tablelist+"\n WHERE "+expr
-    case None => attributelist+"\n"+tablelist
-  }
+case class Select(distinct:Boolean, attributelist:AttributeList, tablelist:TableList, expression:Option[Expression], order:List[OrderElt], offset:Option[Int], limit:Option[Int]) extends SelectORUnion {
+  override def toString = 
+    "SELECT "+
+    { if (distinct) "DISTINCT " else "" }+
+    attributelist+"\n"+
+    tablelist+
+    { if (expression.isDefined) {"\b WHERE " + expression.get + " "} else "" }+
+    { if (order.size > 0) {order.map(o => o.toString).mkString("ORDER BY ", " ", " ") } else "" }+
+    { if (offset.isDefined) {"OFFSET " + offset + " "} else "" }+
+    { if (limit.isDefined) {"LIMIT " + limit + " "} else "" }
 }
 case class Relation(n:Name) extends RelationORSubselect {
   override def toString = n.s /* "'" + n.s + "'" */
@@ -33,7 +38,7 @@
 }
 case class AttributeList(attributes:Set[NamedAttribute]) {
   // foo, bar
-  override def toString = "SELECT "+(attributes.toList.sortWith((l, r) => l.attralias.toString < r.attralias.toString).mkString(", "))
+  override def toString = attributes.toList.sortWith((l, r) => l.attralias.toString < r.attralias.toString).mkString(", ")
 }
 case class NamedAttribute(value:RelVarAttrORExpression, attralias:AttrAlias) {
   override def toString = value + " AS " + attralias
@@ -136,6 +141,9 @@
       case _ => "\"" + i.s + "\""
     }
 }
+case class OrderElt(desc:Boolean, expr:Expression) {
+  override def toString = { if (desc) "DESC" else "ASC" } + "(" + expr.toString + ")"
+}
 case class ConstNULL() extends PrimaryExpression {
   override def toString = "NULL"
 }
@@ -158,7 +166,9 @@
 object Datatype {
   val STRING = Datatype("String")
   val INTEGER = Datatype("Int")
+  val DOUBLE = Datatype("Double")
   val DATE = Datatype("Date")
+  val DATETIME = Datatype("Datetime")
 }
 
 sealed abstract class ValueDescription
@@ -242,7 +252,9 @@
 
   def typpe:Parser[Value] = (
       "INT" ^^ { case _ => Value(Datatype.INTEGER) }
+    | "DOUBLE" ^^ { case _ => Value(Datatype.DOUBLE) }
     | "STRING" ^^ { case _ => Value(Datatype.STRING) }
+    | "DATETIME" ^^ { case _ => Value(Datatype.DATETIME) }
     | "DATE" ^^ { case _ => Value(Datatype.DATE) }
   )
 
@@ -250,9 +262,9 @@
     rep1sep(select, "UNION") ^^ { l => if (l.size == 1) l(0) else Union(l.toSet) }
 
   def select:Parser[Select] =
-    "SELECT" ~ attributelist ~ opt(tablelist) ~ opt(where) ^^
+    "SELECT" ~ opt("DISTINCT") ~ attributelist ~ opt(tablelist) ~ opt(where) ~ opt(order) ~ opt(offset) ~ opt(limit) ^^
     {
-      case "SELECT" ~ attributes ~ tablesANDons ~ whereexpr => {
+      case "SELECT" ~ distinct ~ attributes ~ tablesANDons ~ whereexpr ~ order ~ offset ~ limit => {
 	val (tables, onExpressions) =
 	  tablesANDons.getOrElse((TableList(AddOrderedSet[Join]()), Set[Expression]()))
 	val t:Set[Expression] = onExpressions
@@ -272,10 +284,25 @@
 	  case 1 => Some(conjoints.toList(0))
 	  case _ => Some(ExprConjunction(conjoints))
 	}
-	Select(attributes, tables, expr)
+	Select(distinct.isDefined, attributes, tables, expr, order.getOrElse(List[OrderElt]()), offset, limit)
       }
     }
 
+  def order:Parser[List[OrderElt]] = 
+    "ORDER" ~ "BY" ~ rep(orderelt) ^^ { case o~b~elts => elts }
+
+  def orderelt:Parser[OrderElt] = (
+      "ASC" ~ "(" ~ expression ~ ")" ^^ { case a~o~expr~c => OrderElt(false, expr) }
+    | "DESC" ~ "(" ~ expression ~ ")" ^^ { case a~o~expr~c => OrderElt(true, expr) }
+    | fqattribute ^^ { case v => OrderElt(false, PrimaryExpressionAttr(v)) }
+  )
+    
+  def offset:Parser[Int] =
+    "OFFSET" ~ int ^^ { case o~i => i.toInt }
+
+  def limit:Parser[Int] =
+    "LIMIT" ~ int ^^ { case o~i => i.toInt }
+
   def where:Parser[Expression] =
     "WHERE" ~ expression ^^ { case "WHERE" ~ expression => expression }
 
@@ -347,6 +374,8 @@
       { case primaryexpression ~ "!=" ~ rvalue => RelationalExpressionNe(primaryexpression, rvalue) }
     | primaryexpression ~ "<" ~ primaryexpression ^^
       { case primaryexpression ~ "<" ~ rvalue => RelationalExpressionLt(primaryexpression, rvalue) }
+    | primaryexpression ~ ">" ~ primaryexpression ^^
+      { case primaryexpression ~ ">" ~ rvalue => RelationalExpressionGt(primaryexpression, rvalue) }
     | primaryexpression ~ "IS" ~ "NULL" ^^
       { case primaryexpression ~ "IS" ~ "NULL" => RelationalExpressionNull(primaryexpression) }
     | primaryexpression ~ "IS" ~ "NOT" ~ "NULL" ^^
@@ -369,7 +398,7 @@
 
 case class PrettySql(select:Select) {
   def makePretty():Select = {
-    val Select(attributelist, tablelist, expression) = select
+    val Select(distinct, attributelist, tablelist, expression, order, offset, limit) = select
     val nullStripped =
       if (expression.isDefined) {
 	val nonNullAttrs = PrettySql.findNonNullRelVarAttrs(expression.get)
@@ -394,7 +423,7 @@
 	  case r:Relation => r
 	}}, as), on)
       }})
-    Select(attributelist, TableList(strippedTables), XeqXStripped)
+    Select(distinct, attributelist, TableList(strippedTables), XeqXStripped, order, offset, limit)
   }
 }
 
--- a/src/main/scala/SparqlToSparql.scala	Sun Jun 13 19:31:21 2010 -0400
+++ b/src/main/scala/SparqlToSparql.scala	Sun Jun 13 19:32:44 2010 -0400
@@ -302,10 +302,10 @@
     })
     //println("ruleMap: " + ruleMap)
     sparql.Select(
-      false,
+      query.distinct,
       query.attrs,
       mapGraphPattern(query.gp, ruleMap, "_"),
-      List[sparql.OrderElt](), None, None
+      query.order, query.offset, query.limit
     )
   }
 
--- a/src/main/scala/SparqlToSparqlToSql.scala	Sun Jun 13 19:31:21 2010 -0400
+++ b/src/main/scala/SparqlToSparqlToSql.scala	Sun Jun 13 19:32:44 2010 -0400
@@ -50,11 +50,11 @@
 	val asStem = sparql2sparql.SparqlToSparql(select, List(rule))
 	// println("triple: "+triple)
 	// println("asStem: "+asStem)
-	val sql.Select(sql.AttributeList(attributes), tablelist, expression) = sparql2sql.SparqlToSql(schema, asStem, stemUri, false, true)._1
+	val sql.Select(distinct, sql.AttributeList(attributes), tablelist, expression, order,  offset, limit) = sparql2sql.SparqlToSql(schema, asStem, stemUri, false, true)._1
 	// println("SQL: "+sql.Select(sql.AttributeList(attributes ++ sconsts ++ pconsts ++ oconsts), tablelist, expression))
 
 	/* Add resulting SELECT to list of graph patterns. */
-	gps :+ sql.Select(sql.AttributeList(attributes ++ sconsts ++ pconsts ++ oconsts), tablelist, expression)
+	gps :+ sql.Select(distinct, sql.AttributeList(attributes ++ sconsts ++ pconsts ++ oconsts), tablelist, expression, order, offset, limit)
       })
     })
 
--- a/src/main/scala/SparqlToSql.scala	Sun Jun 13 19:31:21 2010 -0400
+++ b/src/main/scala/SparqlToSql.scala	Sun Jun 13 19:32:44 2010 -0400
@@ -743,13 +743,15 @@
 			   sql.AttrAlias(attrAliasNameFromVar(sparql.VarAssignable(v))))
     ) + pathNo // add join number to selections
     val subselect = sql.Select(
+      false,
       sql.AttributeList(attrlist),
       sql.TableList(nestedState.joins),
       nestedState.exprs.size match {
       	case 0 => None
       	case 1 => Some(nestedState.exprs.toList(0))
       	case _ => Some(sql.ExprConjunction(nestedState.exprs))
-      }
+      },
+      List[sql.OrderElt](), None, None
     )
 
     /** Create a condition to test if this OPTIONAL was matched (called
@@ -854,10 +856,11 @@
 	     */
 	    R2RState(state.joins + sql.InnerJoin(sql.AliasedResource(sql.Subselect(
 	      sql.Select(
+		false, 
 		sql.AttributeList(Set(sql.NamedAttribute(sql.PrimaryExpressionTyped(sql.Datatype.INTEGER,sql.Name("1")),
 							 sql.AttrAlias(sql.Name("_EMPTY_"))))),
 		sql.TableList(util.AddOrderedSet()),
-		None
+		None, List[sql.OrderElt](), None, None
 	      )), sql.RelVar(sql.Name("_EMPTY_"))), None), state.varmap, state.exprs)
 	  else
 	    state
@@ -938,13 +941,14 @@
 	  })
 
 	  val subselect = sql.Select(
+	    false,
 	    sql.AttributeList(attrlist),
 	    sql.TableList(disjointState.joins),
 	    disjointState.exprs.size match {
 	      case 0 => None
 	      case 1 => Some(disjointState.exprs.toList(0))
 	      case _ => Some(sql.ExprConjunction(disjointState.exprs))
-	    }
+	    }, List[sql.OrderElt](), None, None
 	  )
 	  subselects + subselect
 	})
@@ -996,7 +1000,6 @@
    * @return an SQL query corresponding to sparquery
    */
   def apply (db:sql.DatabaseDesc, sparquery:sparql.Select, stem:StemURI, enforceForeignKeys:Boolean, concat:Boolean) : (sql.Select, Map[sparql.Assignable, SQL2RDFValueMapper]) = {
-    val sparql.Select(_, attrs, triples, _, _, _) = sparquery
 
     /** Create an object to hold our compilation state. */
     val initState = R2RState(
@@ -1017,7 +1020,7 @@
      */
     val attrlist:Set[sql.NamedAttribute] =
       // This foldLeft could be a map, if i could coerce to a set afterwards.
-      attrs.attributelist.foldLeft(Set[sql.NamedAttribute]())((attrs, v) => {
+      sparquery.attrs.attributelist.foldLeft(Set[sql.NamedAttribute]())((attrs, v) => {
 	val exp =
 	  if (concat)
 	    // generate CONCAT expression for keys.
@@ -1031,18 +1034,73 @@
 
     /** Construct the generated query as an abstract syntax. */
     val select = sql.Select(
+      sparquery.distinct,
       sql.AttributeList(attrlist),
       sql.TableList(r2rState.joins),
       r2rState.exprs.size match {
 	case 0 => None
 	case 1 => Some(r2rState.exprs.toList(0))
 	case _ => Some(sql.ExprConjunction(r2rState.exprs))
-      }
+      },
+      sparquery.order.map((elt:sparql.OrderElt) => {
+	sql.OrderElt(elt.desc, xxx(r2rState.varmap, elt.expr))
+      }), sparquery.offset, sparquery.limit
     )
     // println("r2rState.varmap: " + r2rState.varmap)
     // println("select.expression: " + select.expression)
     (select.makePretty, r2rState.varmap)
   }
+
+/*
+ * vvv CLEAN THIS UP!!! vvv
+ */
+
+  def assignable2expr999(varmap:Map[sparql.Assignable, SQL2RDFValueMapper], rTerm:sparql.Term):sql.Expression = { // :sparql.Var
+    val r:sql.PrimaryExpression = rTerm match {
+      case sparql.TermUri(u) => error("not implemented: translating RDF URI to SQL: " + u) // :sparql.Uri
+      case sparql.TermVar(v) => sql.PrimaryExpressionAttr(varToAttribute(varmap, sparql.VarAssignable(v)))
+      case sparql.TermBNode(b) => sql.PrimaryExpressionAttr(varToAttribute(varmap, sparql.BNodeAssignable(b)))
+      case sparql.TermLit(sparql.Literal(rdf.RDFLiteral(lit,rdf.Datatype(dt)))) =>
+	sql.PrimaryExpressionTyped({
+	  dt.toString match {
+	    case "http://www.w3.org/2001/XMLSchema#string" => sql.Datatype.STRING
+	    case "http://www.w3.org/2001/XMLSchema#integer" => sql.Datatype.INTEGER
+	    case "http://www.w3.org/2001/XMLSchema#date" => sql.Datatype.DATE
+	    case _ => error("unable to translate to RDF literal SQL: \"" + lit + "\"^^<" + dt + ">")
+	  }
+	}, lit)
+    }
+    r
+  }
+
+  def xxx(varmap:Map[sparql.Assignable, SQL2RDFValueMapper], from:sparql.Expression) : sql.Expression = {
+    val l = from.conjuncts.map((conj) => {
+      conj match {
+	case sparql.SparqlTermExpression(sparql.TermVar(v:sparql.Var)) =>
+	  assignable2expr999(varmap, sparql.TermVar(v))
+	case sparql.SparqlTermExpression(sparql.TermBNode(b:sparql.BNode)) =>
+	  assignable2expr999(varmap, sparql.TermBNode(b))
+	case sparql.SparqlTermExpression(sparql.TermLit(l)) =>
+	  assignable2expr999(varmap, sparql.TermLit(l))
+	case sparql.SparqlTermExpression(sparql.TermUri(u:sparql.Uri)) =>
+	  assignable2expr999(varmap, sparql.TermUri(u))
+	case e:sparql.PrimaryExpression => yyy(varmap, e)
+      }})
+    if (l.size == 1)
+      l(0)
+    else
+      sql.ExprConjunction(l.toSet)
+  }
+
+  def yyy(varmap:Map[sparql.Assignable, SQL2RDFValueMapper], from:sparql.PrimaryExpression) : sql.Expression = {
+    from match {
+      case sparql.SparqlTermExpression(term) => assignable2expr999(varmap, term)
+      case sparql.PrimaryExpressionEq(l, r) => sql.RelationalExpressionEq(yyy(varmap, l), yyy(varmap, r))
+      case sparql.PrimaryExpressionGt(l, r) => sql.RelationalExpressionEq(yyy(varmap, l), yyy(varmap, r))
+      case sparql.PrimaryExpressionLt(l, r) => sql.RelationalExpressionEq(yyy(varmap, l), yyy(varmap, r))
+    }
+  }
+
 }
 
 /**
--- a/src/test/scala/SQLTest.scala	Sun Jun 13 19:31:21 2010 -0400
+++ b/src/test/scala/SQLTest.scala	Sun Jun 13 19:32:44 2010 -0400
@@ -54,10 +54,12 @@
     val e = """
 SELECT 1 AS _TEST_
 """
-    val expected = Select(AttributeList(Set(NamedAttribute(PrimaryExpressionTyped(Datatype.INTEGER,Name("1")),
-							   AttrAlias(Name("_TEST_"))))),
-			  TableList(AddOrderedSet()),
-			  None)
+    val expected = Select(
+      false,
+      AttributeList(Set(NamedAttribute(PrimaryExpressionTyped(Datatype.INTEGER,Name("1")),
+				       AttrAlias(Name("_TEST_"))))),
+      TableList(AddOrderedSet()),
+      None, List[OrderElt](), None, None)
     assert(expected === (a.parseAll(a.select, e).get))
   }
 
@@ -70,14 +72,17 @@
             INNER JOIN Employee AS R_manager
  WHERE R_manager.id=R_emp.manager
 """
-    val expected = Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
-									     Attribute(Name("lastName"))),
-							   AttrAlias(Name("A_empName"))))),
-			  TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
-						  InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_manager"))), None))),
-			  Some(
-			    RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id")))),
-						   PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("manager")))))))
+    val expected = Select(
+      false,
+      AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
+						  Attribute(Name("lastName"))),
+				       AttrAlias(Name("A_empName"))))),
+      TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
+			      InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_manager"))), None))),
+      Some(
+	RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id")))),
+			       PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("manager")))))),
+      List[OrderElt](), None, None)
     assert(expected === (a.parseAll(a.select, e).get))
   }
 
@@ -89,14 +94,17 @@
        FROM Employee AS R_emp
             INNER JOIN Employee AS R_manager ON R_manager.id=R_emp.manager
 """
-    val expected = Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
-									     Attribute(Name("lastName"))),
-							   AttrAlias(Name("A_empName"))))),
-			  TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
-						  InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_manager"))), None))),
-			  Some(
-			    RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id")))),
-						   PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("manager")))))))
+    val expected = Select(
+      false,
+      AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
+						  Attribute(Name("lastName"))),
+				       AttrAlias(Name("A_empName"))))),
+      TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
+			      InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_manager"))), None))),
+      Some(
+	RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id")))),
+			       PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("manager")))))),
+      List[OrderElt](), None, None)
     assert(expected === (a.parseAll(a.select, e).get))
   }
 
@@ -109,19 +117,22 @@
             INNER JOIN Employee AS R_manager
  WHERE R_manager.id=R_emp.manager AND R_emp.lastName IS NOT NULL AND R_manager.lastName IS NOT NULL
 """
-    val expected = Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
-									      Attribute(Name("lastName"))),
-							    AttrAlias(Name("A_empName"))),
-					     NamedAttribute(RelVarAttr(RelVar(Name("R_manager")),
-									      Attribute(Name("lastName"))),
-							    AttrAlias(Name("A_managName"))))),
-			  TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
-					InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_manager"))), None))),
-			  Some(ExprConjunction(Set(
-			    RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id")))),
-						   PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("manager"))))),
-			    RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName"))))),
-			    RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("lastName")))))))))
+    val expected = Select(
+      false,
+      AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
+						  Attribute(Name("lastName"))),
+				       AttrAlias(Name("A_empName"))),
+			NamedAttribute(RelVarAttr(RelVar(Name("R_manager")),
+						  Attribute(Name("lastName"))),
+				       AttrAlias(Name("A_managName"))))),
+      TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
+			      InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_manager"))), None))),
+      Some(ExprConjunction(Set(
+	RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id")))),
+			       PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("manager"))))),
+	RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName"))))),
+	RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("lastName")))))))),
+      List[OrderElt](), None, None)
     assert(expected === (a.parseAll(a.select, e).get))
   }
 
@@ -132,13 +143,16 @@
   FROM Employee AS R_emp
  WHERE R_emp.manager=18 AND R_emp.lastName IS NOT NULL
 """
-    val expected = Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
-									      Attribute(Name("lastName"))),
-							    AttrAlias(Name("A_empName"))))),
-			  TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None))),
-			  Some(ExprConjunction(Set(RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("manager")))),
-									  PrimaryExpressionTyped(Datatype.INTEGER,Name("18"))),
-					  RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName")))))))))
+    val expected = Select(
+      false,
+      AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
+						  Attribute(Name("lastName"))),
+				       AttrAlias(Name("A_empName"))))),
+      TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None))),
+      Some(ExprConjunction(Set(RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("manager")))),
+						      PrimaryExpressionTyped(Datatype.INTEGER,Name("18"))),
+			       RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName")))))))),
+      List[OrderElt](), None, None)
     assert(expected === (a.parseAll(a.select, e).get))
   }
 
@@ -150,16 +164,19 @@
        INNER JOIN Employee AS R_manager
 WHERE R_emp.manager=R_manager.id AND R_manager.lastName="Johnson" AND R_emp.lastName IS NOT NULL
 """
-    val expected = Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
-									      Attribute(Name("lastName"))),
-							    AttrAlias(Name("A_empName"))))),
-			  TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
-					InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_manager"))), None))),
-			  Some(ExprConjunction(Set(RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("manager")))),
-									  PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id"))))),
-					  RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("lastName")))),
-								 PrimaryExpressionTyped(Datatype.STRING,Name("Johnson"))),
-					  RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName")))))))))
+    val expected = Select(
+      false,
+      AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
+						  Attribute(Name("lastName"))),
+				       AttrAlias(Name("A_empName"))))),
+      TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
+			      InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_manager"))), None))),
+      Some(ExprConjunction(Set(RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("manager")))),
+						      PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id"))))),
+			       RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("lastName")))),
+						      PrimaryExpressionTyped(Datatype.STRING,Name("Johnson"))),
+			       RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName")))))))),
+      List[OrderElt](), None, None)
     assert(expected === (a.parseAll(a.select, e).get))
   }
 
@@ -178,29 +195,32 @@
    AND R_grandManager.birthday < R_manager.birthday
    AND R_emp.lastName IS NOT NULL AND R_grandManager.lastName IS NOT NULL
 """
-    val expected = Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")), Attribute(Name("lastName"))),
-							   AttrAlias(Name("A_empName"))),
-					    NamedAttribute(RelVarAttr(RelVar(Name("R_grandManager")),Attribute(Name("lastName"))),
-							   AttrAlias(Name("A_grandManagName"))))),
-			  TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
-					InnerJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_lower"))), None),
-					InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_manager"))), None),
-					InnerJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_upper"))), None),
-					InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_grandManager"))), None))),
-			  Some(ExprConjunction(Set(RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_lower")),Attribute(Name("manages")))),
-									  PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("id"))))),
-					 RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id")))),
-								PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_lower")),Attribute(Name("manager"))))),
-					 RelationalExpressionLt(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("birthday")))),
-								PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("birthday"))))),
-					 RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_upper")),Attribute(Name("manages")))),
-								PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id"))))),
-					 RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_grandManager")),Attribute(Name("id")))),
-								PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_upper")),Attribute(Name("manager"))))),
-					 RelationalExpressionLt(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_grandManager")),Attribute(Name("birthday")))),
-								PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("birthday"))))),
-					 RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName"))))),
-					 RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_grandManager")),Attribute(Name("lastName")))))))))
+    val expected = Select(
+      false,
+      AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")), Attribute(Name("lastName"))),
+				       AttrAlias(Name("A_empName"))),
+			NamedAttribute(RelVarAttr(RelVar(Name("R_grandManager")),Attribute(Name("lastName"))),
+				       AttrAlias(Name("A_grandManagName"))))),
+      TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
+			      InnerJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_lower"))), None),
+			      InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_manager"))), None),
+			      InnerJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_upper"))), None),
+			      InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_grandManager"))), None))),
+      Some(ExprConjunction(Set(RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_lower")),Attribute(Name("manages")))),
+						      PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("id"))))),
+			       RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id")))),
+						      PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_lower")),Attribute(Name("manager"))))),
+			       RelationalExpressionLt(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("birthday")))),
+						      PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("birthday"))))),
+			       RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_upper")),Attribute(Name("manages")))),
+						      PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id"))))),
+			       RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_grandManager")),Attribute(Name("id")))),
+						      PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_upper")),Attribute(Name("manager"))))),
+			       RelationalExpressionLt(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_grandManager")),Attribute(Name("birthday")))),
+						      PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("birthday"))))),
+			       RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName"))))),
+			       RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_grandManager")),Attribute(Name("lastName")))))))),
+      List[OrderElt](), None, None)
     assert(expected === (a.parseAll(a.select, e).get))
   }
 
@@ -222,37 +242,46 @@
        ) AS R_union1
  WHERE R_union1.A_who=R_who.id AND R_who.lastName="Smith"
 """
-    val expected = Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_union1")), Attribute(Name("name"))),
-							   AttrAlias(Name("A_name"))))),
-			  TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_who"))), None),
-					InnerJoin(AliasedResource(Subselect(Union(Set(
-					  Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_manager")), Attribute(Name("lastName"))),
-										  AttrAlias(Name("A_name"))), 
-								   NamedAttribute(RelVarAttr(RelVar(Name("R_above")), Attribute(Name("manages"))),
-										  AttrAlias(Name("A_who"))))),
-						 TableList(AddOrderedSet(
-						   InnerJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_above"))), None),
-						   InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_manager"))), None)
-						 )), 
-						 Some(ExprConjunction(Set(RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_above")),Attribute(Name("manager")))),
-												 PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id"))))),
-								RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("lastName"))))))))), 
-					  Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_managed")), Attribute(Name("lastName"))),
-										  AttrAlias(Name("A_name"))), 
-								   NamedAttribute(RelVarAttr(RelVar(Name("R_below")), Attribute(Name("manager"))),
-										  AttrAlias(Name("A_who"))))),
-						 TableList(AddOrderedSet(
-						   InnerJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_below"))), None),
-						   InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_managed"))), None)
-						 )), 
-						 Some(ExprConjunction(Set(RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_below")),Attribute(Name("manages")))),
-												 PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_managed")),Attribute(Name("id"))))),
-								RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_managed")),Attribute(Name("lastName")))))))))))),
+    val expected = Select(
+      false,
+      AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_union1")), Attribute(Name("name"))),
+				       AttrAlias(Name("A_name"))))),
+      TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_who"))), None),
+			      InnerJoin(AliasedResource(Subselect(Union(Set(
+				Select(
+				  false,
+				  AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_manager")), Attribute(Name("lastName"))),
+								   AttrAlias(Name("A_name"))), 
+						    NamedAttribute(RelVarAttr(RelVar(Name("R_above")), Attribute(Name("manages"))),
+								   AttrAlias(Name("A_who"))))),
+				  TableList(AddOrderedSet(
+				    InnerJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_above"))), None),
+				    InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_manager"))), None)
+				  )), 
+				  Some(ExprConjunction(Set(RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_above")),Attribute(Name("manager")))),
+										  PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("id"))))),
+							   RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_manager")),Attribute(Name("lastName")))))))),
+				  List[OrderElt](), None, None), 
+				Select(
+				  false,
+				  AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_managed")), Attribute(Name("lastName"))),
+								   AttrAlias(Name("A_name"))), 
+						    NamedAttribute(RelVarAttr(RelVar(Name("R_below")), Attribute(Name("manager"))),
+								   AttrAlias(Name("A_who"))))),
+				  TableList(AddOrderedSet(
+				    InnerJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_below"))), None),
+				    InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_managed"))), None)
+				  )), 
+				  Some(ExprConjunction(Set(RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_below")),Attribute(Name("manages")))),
+										  PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_managed")),Attribute(Name("id"))))),
+							   RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_managed")),Attribute(Name("lastName")))))))),
+				  List[OrderElt](), None, None)))),
 							RelVar(Name("R_union1"))), None))), 
-			  Some(ExprConjunction(Set(RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_union1")),Attribute(Name("A_who")))),
-									  PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_who")),Attribute(Name("id"))))),
-					 RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_who")),Attribute(Name("lastName")))),
-								PrimaryExpressionTyped(Datatype.STRING,Name("Smith")))))))
+      Some(ExprConjunction(Set(RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_union1")),Attribute(Name("A_who")))),
+						      PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_who")),Attribute(Name("id"))))),
+			       RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_who")),Attribute(Name("lastName")))),
+						      PrimaryExpressionTyped(Datatype.STRING,Name("Smith")))))),
+      List[OrderElt](), None, None)
     assert(expected === (a.parseAll(a.select, e).get))
   }
 
@@ -263,14 +292,17 @@
                 FROM Manage AS R_above
           WHERE R_above.id IS NOT NULL
 """
-    val expected = Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_above")),
-									      Attribute(Name("manages"))),
-							    AttrAlias(Name("A_who"))),
-					     NamedAttribute(ConstNULL(),
-							    AttrAlias(Name("A_bday"))))),
-			  TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_above"))), None))),
-			  Some(
-			    RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_above")),Attribute(Name("id")))))))
+    val expected = Select(
+      false,
+      AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_above")),
+						  Attribute(Name("manages"))),
+				       AttrAlias(Name("A_who"))),
+			NamedAttribute(ConstNULL(),
+				       AttrAlias(Name("A_bday"))))),
+      TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_above"))), None))),
+      Some(
+	RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_above")),Attribute(Name("id")))))),
+      List[OrderElt](), None, None)
     assert(expected === (a.parseAll(a.select, e).get))
   }
 
@@ -281,16 +313,17 @@
 SELECT CONCAT(""" + QuotedBaseURI + """, "Employee", "/", "id", ".", R_emp.id, "#record") AS A_emp
        FROM Employee AS R_emp
 """
-    val expected = Select(AttributeList(Set(NamedAttribute(Concat(List(PrimaryExpressionTyped(Datatype("String"),Name("http://hr.example/DB/")),
-								       PrimaryExpressionTyped(Datatype("String"),Name("Employee")),
-								       PrimaryExpressionTyped(Datatype("String"),Name("/")),
-								       PrimaryExpressionTyped(Datatype("String"),Name("id")),
-								       PrimaryExpressionTyped(Datatype("String"),Name(".")),
-								       PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("id")))),
-								       PrimaryExpressionTyped(Datatype("String"),Name("#record")))),
-							    AttrAlias(Name("A_emp"))))),
-			  TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None))),
-			  None)
+    val expected = Select(
+      false, AttributeList(Set(NamedAttribute(Concat(List(PrimaryExpressionTyped(Datatype("String"),Name("http://hr.example/DB/")),
+							  PrimaryExpressionTyped(Datatype("String"),Name("Employee")),
+							  PrimaryExpressionTyped(Datatype("String"),Name("/")),
+							  PrimaryExpressionTyped(Datatype("String"),Name("id")),
+							  PrimaryExpressionTyped(Datatype("String"),Name(".")),
+							  PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("id")))),
+							  PrimaryExpressionTyped(Datatype("String"),Name("#record")))),
+					      AttrAlias(Name("A_emp"))))),
+      TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None))),
+      None, List[OrderElt](), None, None)
     assert(expected === (a.parseAll(a.select, e).get))
   }
 
@@ -301,21 +334,24 @@
                 FROM Manage AS R_above
           WHERE (R_above.id IS NOT NULL) OR (R_above.id < 5 AND R_above.id < 3)
 """
-    val expected = Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_above")),
-									      Attribute(Name("manages"))),
-							    AttrAlias(Name("A_who"))),
-					     NamedAttribute(ConstNULL(),
-							    AttrAlias(Name("A_bday"))))),
-			  TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_above"))), None))),
-			  Some(
-			    ExprDisjunction(Set(
-			      RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_above")),Attribute(Name("id"))))),
-			      ExprConjunction(Set(
-				RelationalExpressionLt(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_above")),Attribute(Name("id")))),
-						       PrimaryExpressionTyped(Datatype.INTEGER,Name("5"))),
-				RelationalExpressionLt(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_above")),Attribute(Name("id")))),
-						       PrimaryExpressionTyped(Datatype.INTEGER,Name("3")))
-			      ))))))
+    val expected = Select(
+      false,
+      AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_above")),
+						  Attribute(Name("manages"))),
+				       AttrAlias(Name("A_who"))),
+			NamedAttribute(ConstNULL(),
+				       AttrAlias(Name("A_bday"))))),
+      TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_above"))), None))),
+      Some(
+	ExprDisjunction(Set(
+	  RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_above")),Attribute(Name("id"))))),
+	  ExprConjunction(Set(
+	    RelationalExpressionLt(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_above")),Attribute(Name("id")))),
+				   PrimaryExpressionTyped(Datatype.INTEGER,Name("5"))),
+	    RelationalExpressionLt(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_above")),Attribute(Name("id")))),
+				   PrimaryExpressionTyped(Datatype.INTEGER,Name("3")))
+	  ))))),
+      List[OrderElt](), None, None)
     assert(expected === (a.parseAll(a.select, e).get))
   }
 
@@ -327,20 +363,23 @@
             LEFT OUTER JOIN Manage AS R_mang ON R_mang.emp=R_emp.id
  WHERE R_emp.lastName IS NOT NULL
 """
-    val expected = Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
-									     Attribute(Name("lastName"))),
-							    AttrAlias(Name("A_empName"))),
-					     NamedAttribute(RelVarAttr(RelVar(Name("R_mang")),
-									      Attribute(Name("manageName"))),
-							    AttrAlias(Name("A_manageName"))))),
-			  TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
-					LeftOuterJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_mang"))),
-						      RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_mang")),Attribute(Name("emp")))),
-									     PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("id"))))
-									   )))),
-			  Some(
-			      RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName")))))
-			    ))
+    val expected = Select(
+      false,
+      AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
+						  Attribute(Name("lastName"))),
+				       AttrAlias(Name("A_empName"))),
+			NamedAttribute(RelVarAttr(RelVar(Name("R_mang")),
+						  Attribute(Name("manageName"))),
+				       AttrAlias(Name("A_manageName"))))),
+      TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
+			      LeftOuterJoin(AliasedResource(Relation(Name("Manage")),RelVar(Name("R_mang"))),
+					    RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_mang")),Attribute(Name("emp")))),
+								   PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("id"))))
+								 )))),
+      Some(
+	RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName")))))
+      ),
+      List[OrderElt](), None, None)
     assert(expected === (a.parseAll(a.select, e).get))
   }
 
@@ -356,18 +395,23 @@
  WHERE R_emp.lastName IS NOT NULL
 """
     val expected = 
-      Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName"))),AttrAlias(Name("A_empName"))),
-			       NamedAttribute(RelVarAttr(RelVar(Name("R_mang")),Attribute(Name("manageName"))),AttrAlias(Name("A_manageName"))))),
-	     TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
-			   LeftOuterJoin(AliasedResource(
-			     Subselect(Select(AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName"))),AttrAlias(Name("A_empName"))),
-						      NamedAttribute(RelVarAttr(RelVar(Name("R_mang")),Attribute(Name("manageName"))),AttrAlias(Name("A_manageName"))))),
-				    TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None))),
-				    None)),
-			     RelVar(Name("R_mang"))),
-					 RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_mang")),Attribute(Name("emp")))),
-								PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("id")))))))),
-	     Some(RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName")))))))
+      Select(
+	false,
+	AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName"))),AttrAlias(Name("A_empName"))),
+			  NamedAttribute(RelVarAttr(RelVar(Name("R_mang")),Attribute(Name("manageName"))),AttrAlias(Name("A_manageName"))))),
+	TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None),
+				LeftOuterJoin(AliasedResource(
+				  Subselect(Select(
+				    false,
+				    AttributeList(Set(NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName"))),AttrAlias(Name("A_empName"))),
+								     NamedAttribute(RelVarAttr(RelVar(Name("R_mang")),Attribute(Name("manageName"))),AttrAlias(Name("A_manageName"))))),
+						   TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None))),
+				    None, List[OrderElt](), None, None)),
+				  RelVar(Name("R_mang"))),
+					      RelationalExpressionEq(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_mang")),Attribute(Name("emp")))),
+								     PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("id")))))))),
+	Some(RelationalExpressionNotNull(PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("lastName")))))),
+	List[OrderElt](), None, None)
     assert(expected === (a.parseAll(a.select, e).get))
   }
 
@@ -496,22 +540,24 @@
             R_emp.lastName AS O
        FROM Employee AS R_emp
 """ // "
-    val expected = View(Relation(Name("triples")), Select(AttributeList(Set(
-      NamedAttribute(Concat(List(PrimaryExpressionTyped(Datatype("String"),Name("http://hr.example/DB/")),
-				 PrimaryExpressionTyped(Datatype("String"),Name("Employee")),
-				 PrimaryExpressionTyped(Datatype("String"),Name("/")),
-				 PrimaryExpressionTyped(Datatype("String"),Name("empid")),
-				 PrimaryExpressionTyped(Datatype("String"),Name(".")),
-				 PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("id")))),
-				 PrimaryExpressionTyped(Datatype("String"),Name("#record")))),
-		     AttrAlias(Name("S"))),
-      NamedAttribute(PrimaryExpressionTyped(Datatype.STRING,Name("<http://hr.example/DB/Employee#lastName>")),
-		     AttrAlias(Name("P"))),
-      NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
-				Attribute(Name("lastName"))),
-		     AttrAlias(Name("O"))))), 
-			  TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None))),
-			  None))
+    val expected = View(Relation(Name("triples")), Select(
+      false,
+      AttributeList(Set(
+	NamedAttribute(Concat(List(PrimaryExpressionTyped(Datatype("String"),Name("http://hr.example/DB/")),
+				   PrimaryExpressionTyped(Datatype("String"),Name("Employee")),
+				   PrimaryExpressionTyped(Datatype("String"),Name("/")),
+				   PrimaryExpressionTyped(Datatype("String"),Name("empid")),
+				   PrimaryExpressionTyped(Datatype("String"),Name(".")),
+				   PrimaryExpressionAttr(RelVarAttr(RelVar(Name("R_emp")),Attribute(Name("id")))),
+				   PrimaryExpressionTyped(Datatype("String"),Name("#record")))),
+		       AttrAlias(Name("S"))),
+	NamedAttribute(PrimaryExpressionTyped(Datatype.STRING,Name("<http://hr.example/DB/Employee#lastName>")),
+		       AttrAlias(Name("P"))),
+	NamedAttribute(RelVarAttr(RelVar(Name("R_emp")),
+				  Attribute(Name("lastName"))),
+		       AttrAlias(Name("O"))))), 
+      TableList(AddOrderedSet(InnerJoin(AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp"))), None))),
+      None, List[OrderElt](), None, None))
     assert(expected === (a.parseAll(a.createview, e).get))
   }
 
--- a/src/test/scala/SparqlToSparqlToSqlTest.scala	Sun Jun 13 19:31:21 2010 -0400
+++ b/src/test/scala/SparqlToSparqlToSqlTest.scala	Sun Jun 13 19:32:44 2010 -0400
@@ -5,6 +5,7 @@
 package w3c.sw
 
 import org.scalatest.FunSuite
+import scala.util.matching.Regex
 import java.net.URI
 import w3c.sw.sparql.Sparql
 import w3c.sw.sparql2sparql.{SparqlToSparql}
@@ -333,29 +334,156 @@
 """
   }
 
-  // test("hospital as view") {
-  //   val sparqlParser = Sparql()
-  //   println("hospital view...")
-  //   val view = toView(List(db2hl7), hosp1, StemURI("http://hospital.example/DB/"))
-  //   println("hospital view: " + view)
-//     val sqlParser = Sql()
-//     val expected = sqlParser.parseAll(sqlParser.createview, """
-// """).get
-//     assert(expected === view)
-  // }
+/*
+  test("hospital as view") {
+    val sparqlParser = Sparql()
+    println("hospital view...")
+    val view = toView(List(db2hl7), hosp1, StemURI("http://hospital.example/DB/"))
+    println("hospital view: " + view)
+    val sqlParser = Sql()
+    val expected = sqlParser.parseAll(sqlParser.createview, """
+""").get
+    assert(expected === view)
+  }
+ */
 
-  /* ========== DiabeticPatient database tests ==========
+  /* ========== BSBM database tests ==========
    *
    */
   val bsbmDdl = """
-CREATE TABLE Person (ID INT PRIMARY KEY, MiddleName STRING, DateOfBirth DATE, SexDE INT, PRIMARY KEY (ID), FOREIGN KEY (SexDE) REFERENCES Sex_DE(ID));
-CREATE TABLE Sex_DE (ID INT PRIMARY KEY, EntryName STRING);
-CREATE TABLE Item_Medication (ID INT PRIMARY KEY, PRIMARY KEY (ID), PatientID INT, FOREIGN KEY (PatientID) REFERENCES Person(ID), PerformedDTTM DATE, EntryName STRING);
-CREATE TABLE Medication (ID INT PRIMARY KEY, PRIMARY KEY (ID), ItemID INT, FOREIGN KEY (ItemID) REFERENCES Item_Medication(ID), MedDictDE INT, FOREIGN KEY (MedDictDE) REFERENCES Medication_DE(ID), DaysToTake INT);
-CREATE TABLE Medication_DE (ID INT PRIMARY KEY, NDC INT);
-CREATE TABLE NDCcodes (ID INT PRIMARY KEY, NDC INT, ingredient INT);
+CREATE TABLE offer (
+  nr INT,
+  product INT,
+  producer INT,
+  vendor INT,
+  price DOUBLE,
+  validFrom DATETIME,
+  validTo DATETIME,
+  deliveryDays INT,
+  offerWebpage STRING,
+  publisher INT,
+  publishDate DATE,
+  PRIMARY KEY (nr)
+);
+
+
+CREATE TABLE person (
+  nr INT,
+  name STRING,
+  mbox_sha1sum STRING,
+  country STRING,
+  publisher INT,
+  publishDate DATE,
+  PRIMARY KEY (nr)
+);
+
+
+CREATE TABLE producer (
+  nr INT,
+  label STRING,
+  comment STRING,
+  homepage STRING,
+  country STRING,
+  publisher INT,
+  publishDate DATE,
+  PRIMARY KEY (nr)
+);
+
+
+CREATE TABLE product (
+  nr INT,
+  label STRING,
+  comment STRING,
+  producer INT,
+  propertyNum1 INT,
+  propertyNum2 INT,
+  propertyNum3 INT,
+  propertyNum4 INT,
+  propertyNum5 INT,
+  propertyNum6 INT,
+  propertyTex1 STRING,
+  propertyTex2 STRING,
+  propertyTex3 STRING,
+  propertyTex4 STRING,
+  propertyTex5 STRING,
+  propertyTex6 STRING,
+  publisher INT,
+  publishDate DATE,
+  PRIMARY KEY (nr)
+);
+
+
+CREATE TABLE productfeature (
+  nr INT,
+  label STRING,
+  comment STRING,
+  publisher INT,
+  publishDate DATE,
+  PRIMARY KEY (nr)
+);
+
+
+CREATE TABLE productfeatureproduct (
+  product INT,
+  productFeature INT,
+  PRIMARY KEY (productFeature)
+);
+
+
+CREATE TABLE producttype (
+  nr INT,
+  label STRING,
+  comment STRING,
+  parent INT,
+  publisher INT,
+  publishDate DATE,
+  PRIMARY KEY (nr)
+);
+
+
+CREATE TABLE producttypeproduct (
+  product INT,
+  productType INT,
+  PRIMARY KEY (productType)
+);
+
+
+CREATE TABLE review (
+  nr INT,
+  product INT,
+  producer INT,
+  person INT,
+  reviewDate DATETIME,
+  title STRING,
+  text STRING,
+  language STRING,
+  rating1 INT,
+  rating2 INT,
+  rating3 INT,
+  rating4 INT,
+  publisher INT,
+  publishDate DATE,
+  PRIMARY KEY (nr)
+);
+
+
+CREATE TABLE vendor (
+  nr INT,
+  label STRING,
+  comment STRING,
+  homepage STRING,
+  country STRING,
+  publisher INT,
+  publishDate DATE,
+  PRIMARY KEY (nr)
+);
 """
+  /*
+   productfeatureproduct ( PRIMARY KEY (product,productFeature) );
+   producttypeproduct ( PRIMARY KEY (product,productType) );
+   */
   val bsbmDb:DatabaseDesc = DDLParser.parseAll(DDLParser.ddl, bsbmDdl).get
+
   val delme = Sparql() // re-use ConstructParser ?
   val db2bsbm = delme.parseAll(delme.construct, """
 PREFIX map: <file:/E:/code/d2r-server-0.4/d2r-mapping.n3#>
@@ -384,14 +512,21 @@
 PREFIX tr: <http://www.w3.org/2008/04/SPARQLfed/#>
 
 CONSTRUCT {
-<s> <p> <o> .
+  ?product    a bsbm:Product .
+     ?product bsbm:productFeature ?pfp .
+     ?product rdf:type ?ptp .
+     ?product rdfs:label ?p_label .
+     ?product bsbm:productPropertyNumeric1 ?lit_propertyNum1 .
 } WHERE {
-<s> <p> <o> .
+  ?product product:label ?p_label .
+     ?product product:propertyNum1 ?lit_propertyNum1 .
+  ?pfp     productfeatureproduct:product ?product .
+  ?ptp     producttypeproduct:product ?product .
 }""" //"
 			      ).get
   test("bsbm1") {
     val sparqlParser = Sparql()
-    val bsbmQuery = sparqlParser.parseAll(sparqlParser.select, """
+    val queryStr = """
 PREFIX bsbm-inst: <http://www4.wiwiss.fu-berlin.de/bizer/bsbm/v01/instances/>
 PREFIX bsbm: <http://www4.wiwiss.fu-berlin.de/bizer/bsbm/v01/vocabulary/>
 PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
@@ -408,28 +543,55 @@
 	}
 ORDER BY ?label
 LIMIT 10
+"""
+    .replaceAll("<http://www4.wiwiss.fu-berlin.de/bizer/bsbm/v01/instances/ProductFeature([0-9]+)>",
+		"<http://bsbm.example/db/productfeatureproduct/productFeature.$1#record>")
+    .replaceAll("<http://www4.wiwiss.fu-berlin.de/bizer/bsbm/v01/instances/ProductType([0-9]+)>",
+		"<http://bsbm.example/db/producttypeproduct/productType.$1#record>")
+
+    val bsbmQuery = sparqlParser.parseAll(sparqlParser.select, queryStr).get
+
+    val stemExpected = sparqlParser.parseAll(sparqlParser.select, """
+PREFIX product: <http://bsbm.example/db/product#>
+PREFIX pfp: <http://bsbm.example/db/productfeatureproduct#>
+PREFIX ptp: <http://bsbm.example/db/producttypeproduct#>
+
+SELECT DISTINCT ?product ?label WHERE {
+  ?product product:label        ?label .
+  ?product product:propertyNum1 ?value1 .
+  <http://bsbm.example/db/producttypeproduct/productType.59#record>   ptp:product ?product .
+  <http://bsbm.example/db/productfeatureproduct/productFeature.5#record> pfp:product ?product .
+  <http://bsbm.example/db/productfeatureproduct/productFeature.7#record> pfp:product ?product .
+  FILTER (?value1 > 578)
+}
+ORDER BY ?label
+LIMIT 10
 """).get
 
-    val stemQuery = sparqlParser.parseAll(sparqlParser.select, """
-SELECT ?o WHERE { ?s <p> ?o }
-""").get
     val sqlParser = Sql()
-    val sqlQuery = sqlParser.parseAll(sqlParser.select, """
-SELECT R_emp.empid AS emp
-  FROM Employee AS R_emp
- WHERE R_emp.empid IS NOT NULL AND R_emp.lastName="Smith"
+    val sqlExpected = sqlParser.parseAll(sqlParser.select, """
+SELECT DISTINCT R_product.label AS label, R_product.nr AS product
+  FROM product AS R_product
+       INNER JOIN producttypeproduct AS R_productType59
+	       ON R_productType59.product=R_product.nr
+                  AND R_productType59.productType=59
+       INNER JOIN productfeatureproduct AS R_productFeature5
+               ON R_productFeature5.product=R_product.nr
+                  AND R_productFeature5.productFeature=5
+       INNER JOIN productfeatureproduct AS R_productFeature7
+               ON R_productFeature7.product=R_product.nr
+                  AND R_productFeature7.productFeature=7
+ WHERE R_product.propertyNum1 > 578
+   AND R_product.label IS NOT NULL
+ORDER BY R_product.label
+LIMIT 10
 """).get
-//     val asStem = SparqlToSparql(bsbmQuery, List(db2bsbm))
-//     if (!(asStem == stemQuery)) {
-//       println(asStem.toString())
-//       println("---")
-//       println(stemQuery.toString())
-//     }
-//     assert(asStem == stemQuery)
-//     val asSql = SparqlToSql(bsbmDb, asStem, StemURI("http://hospital.example/DB/"), false, false)._1
-//     assert(asSql === sqlQuery)
-//     val output = """
-// """
+    val asStem = SparqlToSparql(bsbmQuery, List(db2bsbm))
+    assert(stemExpected === asStem)
+    val (asSql, _) = SparqlToSql(bsbmDb, asStem, StemURI("http://bsbm.example/db/"), false, false)
+    assert(sqlExpected === asSql)
+    val output = """
+"""
   }
 
 }