Created
May 25, 2019 06:57
-
-
Save karthik20522/e10623b0273d204d750906d587a54ed2 to your computer and use it in GitHub Desktop.
Scala Query Parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.scalatest.matchers.ShouldMatchers | |
import org.scalatest._ | |
class SQLParserSpec extends FunSpec with ShouldMatchers { | |
val p = new SQLParser | |
describe("given a sql string with an order clause") { | |
describe("(when direction is asc)") { | |
val sql = "select name from users order by name asc" | |
it("should be parsed into an Asc object containing the given field") { | |
val query = p.parse(sql).get | |
query.operation should be(Select("name")) | |
query.from should be(From("users")) | |
query.order should be(Option(Asc("name"))) | |
} | |
} | |
} | |
describe("given a sql string with a single where clause") { | |
describe("(when equals predicate with string literal)") { | |
val sql = "select name from users where name = \"peter\"" | |
it("should be parsed into an StringEquals object containing the given field and value") { | |
val query = p.parse(sql).get | |
query.operation should be(Select("name")) | |
query.from should be(From("users")) | |
query.where.get.clauses.head should be(StringEquals("name", "peter")) | |
} | |
} | |
describe("(when equals predicate with numeric literal)") { | |
val sql = """select age from users where age = 30""" | |
it("should be parsed into an NumberEquals object containing the given field and value") { | |
val query = p.parse(sql).get | |
query.operation should be(Select("age")) | |
query.from should be(From("users")) | |
query.where.get.clauses.head should be(NumberEquals("age", 30)) | |
} | |
} | |
} | |
describe("given a sql string with a combined where clause") { | |
describe("(when equals predicate contains and)") { | |
val sql = """select name from users where name = "peter" and age = 30""" | |
it("should be parsed into an And object containing to correct subclauses") { | |
val query = p.parse(sql).get | |
query.operation should be(Select("name")) | |
query.from should be(From("users")) | |
query.where.get.clauses.head should be(And(StringEquals("name", "peter"), NumberEquals("age", 30))) | |
} | |
} | |
describe("(when equals predicate contains or)") { | |
val sql = """select name from users where age = 20 or age = 30""" | |
it("should be parsed into an Or object containing to correct subclauses") { | |
val query = p.parse(sql).get | |
query.operation should be(Select("name")) | |
query.from should be(From("users")) | |
query.where.get.clauses.head should be(Or(NumberEquals("age", 20), NumberEquals("age", 30))) | |
} | |
} | |
describe("(when equals predicate contains multiple combined clauses)") { | |
val sql = """select name from users where name = "peter" and age = 20 or age = 30""" | |
it("should be parsed into an Or object containing and And object and and Equals predicate") { | |
val query = p.parse(sql).get | |
query.operation should be(Select("name")) | |
query.from should be(From("users")) | |
query.where.get.clauses.head should be(Or(And(StringEquals("name", "peter"), NumberEquals("age", 20)), NumberEquals("age", 30))) | |
} | |
} | |
describe("(when greater than predicate is provided)") { | |
val sql = """select name from users where age > 30""" | |
it("should be parsed into an GreaterThan object") { | |
val query = p.parse(sql).get | |
query.operation should be(Select("name")) | |
query.from should be(From("users")) | |
query.where.get.clauses.head should be(GreaterThan("age", 30)) | |
} | |
} | |
describe("(when predicate contains equals and greatherThan clauses)") { | |
val sql = """select name from users where age > 30 and name = "peter"""" | |
it("should be parsed into an AND object with correct equal and greaterThan clauses") { | |
val query = p.parse(sql).get | |
query.operation should be(Select("name")) | |
query.from should be(From("users")) | |
query.where.get.clauses.head should be(And(GreaterThan("age", 30), StringEquals("name", "peter"))) | |
} | |
} | |
describe("(when equals predicate contains multiple combined clauses where the presedence is dictated by parens)") { | |
val sql = """select name,age from users where name = "peter" and (active = true or age = 30)""" | |
it("should be parsed into an Or object containing and And object and and Equals predicate") { | |
val query = p.parse(sql).get | |
query.operation should be(Select(List[String]("name", "age"): _*)) | |
query.from should be(From("users")) | |
query.where.get.clauses.head should be(And(StringEquals("name", "peter"), Or(BooleanEquals("active", true), NumberEquals("age", 30)))) | |
} | |
} | |
describe("(when just limit filter is provided)") { | |
val sql = "select name from users limit 22" | |
it("should be parsed into an limit object") { | |
val query = p.parse(sql).get | |
query.operation should be(Select("name")) | |
query.from should be(From("users")) | |
query.limit should be(Option(Limit(22))) | |
} | |
} | |
describe("(when limit filter along with order and where clause)") { | |
val sql = "select name from users where age > 30 order by age desc limit 22" | |
it("should be parsed into an limit object") { | |
val query = p.parse(sql).get | |
query.operation should be(Select("name")) | |
query.from should be(From("users")) | |
query.where.get.clauses.head should be(GreaterThan("age", 30)) | |
query.order should be(Option(Desc("age"))) | |
query.limit should be(Option(Limit(22))) | |
} | |
} | |
describe("(when mutliple order clause)") { | |
val sql = "select name from users order by age, name desc" | |
it("should be parsed into an multiple order object") { | |
val query = p.parse(sql).get | |
query.operation should be(Select("name")) | |
query.from should be(From("users")) | |
query.order should be(Option(Desc("age", "name"))) | |
} | |
} | |
describe("(when predicate contains like clauses)") { | |
val sql = """select name from users where age > 30 and name like "peter"""" | |
it("should be parsed into an AND object with correct like and greaterThan clauses") { | |
val query = p.parse(sql).get | |
query.operation should be(Select("name")) | |
query.from should be(From("users")) | |
query.where.get.clauses.head should be(And(GreaterThan("age", 30), Like("name", "peter"))) | |
} | |
} | |
describe("(when predicate contains count clauses)") { | |
val sql = """select count(name) from users where age > 30 and name like "peter"""" | |
it("should be parsed into an AND object with correct like and greaterThan clauses") { | |
val query = p.parse(sql).get | |
query.operation should be(Count("name")) | |
query.from should be(From("users")) | |
query.where.get.clauses.head should be(And(GreaterThan("age", 30), Like("name", "peter"))) | |
} | |
} | |
} | |
describe("given invalid sql string") { | |
describe("(when bad select statement is provided)") { | |
val sql = "select from users" | |
it("should throw an exception") { | |
intercept[Exception] { | |
val query = p.parse(sql).get | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment