+ optional FROM tablelist
authorEric Prud'hommeaux <bertails@w3.org>
Thu, 07 Jan 2010 09:31:42 -0500
changeset 117 11e5b3672a69
parent 116 f4fa891ab93c
child 118 0ea6cb8f981a
+ optional FROM tablelist
src/main/scala/SQL.scala
src/test/scala/SQLTest.scala
--- a/src/main/scala/SQL.scala	Wed Jan 06 17:24:50 2010 -0500
+++ b/src/main/scala/SQL.scala	Thu Jan 07 09:31:42 2010 -0500
@@ -54,11 +54,15 @@
   override def toString = n.s /* "'" + n.s + "'" */
 }
 case class TableList(joins:AddOrderedSet[Join]) {
-  override def toString = "  FROM " + joins.foldLeft(("", 0))(
-    (pair, entry) => (pair._1 + {
-      if (pair._2 == 0) entry.toString.substring(19) // !!! shameless!
-      else entry
-    }, pair._2+1))._1
+  override def toString = 
+    if (joins.size == 0) ""
+    else {
+      "  FROM " + joins.foldLeft(("", 0))(
+	(pair, entry) => (pair._1 + {
+	  if (pair._2 == 0) entry.toString.substring(19) // !!! shameless!
+	  else entry
+	}, pair._2+1))._1
+    }
 }
 
 sealed abstract class Join(res:AliasedResource)
@@ -137,11 +141,14 @@
     rep1sep(select, "UNION") ^^ { l => if (l.size == 1) l(0) else Union(l.toSet) }
 
   def select:Parser[Select] =
-    "SELECT" ~ attributelist ~ "FROM" ~ tablelist ~ opt(where) ^^
+    "SELECT" ~ attributelist ~ opt(tablelist) ~ opt(where) ^^
     {
-      case "SELECT" ~ attributes ~ "FROM" ~ tablesANDons ~ whereexpr => {
-	val t:Set[Expression] = tablesANDons._2
-	val onConjoints:Set[Expression] = tablesANDons._2.foldLeft(Set[Expression]())((s, ent) =>
+      case "SELECT" ~ attributes ~ tablesANDons ~ whereexpr => {
+	val (tables, onExpressions) =
+	  tablesANDons.getOrElse((TableList(AddOrderedSet[Join]()), Set[Expression]()))
+	val t:Set[Expression] = onExpressions
+	val onConjoints:Set[Expression] =
+	  onExpressions.foldLeft(Set[Expression]())((s, ent) =>
 	  s ++ {ent match {
 	    case ExprConjunction(l) => l
 	    case _ => Set(ent)
@@ -156,7 +163,7 @@
 	  case 1 => Some(conjoints.toList(0))
 	  case _ => Some(ExprConjunction(conjoints))
 	}
-	Select(attributes, tablesANDons._1, expr)
+	Select(attributes, tables, expr)
       }
     }
 
@@ -195,8 +202,9 @@
     """[a-zA-Z_]\w*""".r ^^ { x => RelAlias(Name(x)) }
 
   def tablelist:Parser[(TableList, Set[Expression])] =
-    aliasedjoin ~ rep(innerORouter) ^^ { case aj~l => (TableList(AddOrderedSet(InnerJoin(aj) :: l.map((one) => one._1))), 
-						       l.foldLeft(Set[Expression]())((all, one) => all ++ one._2)) }
+    "FROM" ~ aliasedjoin ~ rep(innerORouter) ^^
+    { case "FROM"~aj~l => (TableList(AddOrderedSet(InnerJoin(aj) :: l.map((one) => one._1))), 
+			   l.foldLeft(Set[Expression]())((all, one) => all ++ one._2)) }
 
   def innerORouter:Parser[(Join, Set[Expression])] = (
       "INNER" ~ "JOIN" ~ aliasedjoin ~ opt("ON" ~ expression) ^^
--- a/src/test/scala/SQLTest.scala	Wed Jan 06 17:24:50 2010 -0500
+++ b/src/test/scala/SQLTest.scala	Thu Jan 07 09:31:42 2010 -0500
@@ -48,6 +48,19 @@
     assert(expected === (a.parseAll(a.expression, e).get))
   }
 
+  test("parse no FROM") {
+    // AliasedResource(Relation(Name("Employee")),RelAlias(Name("R_emp")))
+    val a = Sql()
+    val e = """
+SELECT 1 AS _TEST_
+"""
+    val expected = Select(AttributeList(Set(NamedAttribute(PrimaryExpressionTyped(Datatype.INTEGER,Name("1")),
+							   AttrAlias(Name("_TEST_"))))),
+			  TableList(AddOrderedSet()),
+			  None)
+    assert(expected === (a.parseAll(a.select, e).get))
+  }
+
   test("parse WHERE") {
     // AliasedResource(Relation(Name("Employee")),RelAlias(Name("R_emp")))
     val a = Sql()