Home | History | Annotate | Download | only in parser
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package androidx.room.parser
     18 
     19 import org.hamcrest.CoreMatchers.`is`
     20 import org.hamcrest.CoreMatchers.not
     21 import org.hamcrest.MatcherAssert.assertThat
     22 import org.junit.Test
     23 import org.junit.runner.RunWith
     24 import org.junit.runners.JUnit4
     25 
     26 @RunWith(JUnit4::class)
     27 class SqlParserTest {
     28 
     29     @Test
     30     fun multipleQueries() {
     31         assertErrors("SELECT * FROM users; SELECT * FROM books;",
     32                 ParserErrors.NOT_ONE_QUERY)
     33     }
     34 
     35     @Test
     36     fun empty() {
     37         assertErrors("", ParserErrors.NOT_ONE_QUERY)
     38     }
     39 
     40     @Test
     41     fun deleteQuery() {
     42         val parsed = SqlParser.parse("DELETE FROM users where id > 3")
     43         assertThat(parsed.errors, `is`(emptyList()))
     44         assertThat(parsed.type, `is`(QueryType.DELETE))
     45     }
     46 
     47     @Test
     48     fun badDeleteQuery() {
     49         assertErrors("delete from user where mAge >= :min && mAge <= :max",
     50                 "no viable alternative at input 'delete from user where mAge >= :min &&'")
     51     }
     52 
     53     @Test
     54     fun updateQuery() {
     55         val parsed = SqlParser.parse("UPDATE users set name = :name where id = :id")
     56         assertThat(parsed.errors, `is`(emptyList()))
     57         assertThat(parsed.type, `is`(QueryType.UPDATE))
     58     }
     59 
     60     @Test
     61     fun explain() {
     62         assertErrors("EXPLAIN QUERY PLAN SELECT * FROM users",
     63                 ParserErrors.invalidQueryType(QueryType.EXPLAIN))
     64     }
     65 
     66     @Test
     67     fun validColumnNames() {
     68         listOf("f", "fo", "f2", "f 2", "foo_2", "foo-2", "_", "foo bar baz",
     69                 "foo 2 baz", "_baz", "fooBar", "2", "*", "foo*2", "dsa$", "\$fsa",
     70                 "-bar", "o").forEach {
     71             assertThat("name: $it", SqlParser.isValidIdentifier(it), `is`(true))
     72         }
     73     }
     74 
     75     @Test
     76     fun invalidColumnNames() {
     77         listOf("", " ", "fd`a`", "f`a", "`a", "\"foo bar\"", "\"", "`").forEach {
     78             assertThat("name: $it", SqlParser.isValidIdentifier(it), `is`(false))
     79         }
     80     }
     81 
     82     @Test
     83     fun extractTableNames() {
     84         assertThat(SqlParser.parse("select * from users").tables,
     85                 `is`(setOf(Table("users", "users"))))
     86         assertThat(SqlParser.parse("select * from users as ux").tables,
     87                 `is`(setOf(Table("users", "ux"))))
     88         assertThat(SqlParser.parse("select * from (select * from books)").tables,
     89                 `is`(setOf(Table("books", "books"))))
     90         assertThat(SqlParser.parse("select x.id from (select * from books) as x").tables,
     91                 `is`(setOf(Table("books", "books"))))
     92     }
     93 
     94     @Test
     95     fun unescapeTableNames() {
     96         assertThat(SqlParser.parse("select * from `users`").tables,
     97                 `is`(setOf(Table("users", "users"))))
     98         assertThat(SqlParser.parse("select * from \"users\"").tables,
     99                 `is`(setOf(Table("users", "users"))))
    100         assertThat(SqlParser.parse("select * from 'users'").tables,
    101                 `is`(setOf(Table("users", "users"))))
    102     }
    103 
    104     @Test
    105     fun tablePrefixInInsert_set() {
    106         // this is an invalid query, b/64539805
    107         val query = SqlParser.parse("UPDATE trips SET trips.title=:title")
    108         assertThat(query.errors, not(emptyList()))
    109     }
    110 
    111     @Test
    112     fun tablePrefixInInsert_where() {
    113         val query = SqlParser.parse("UPDATE trips SET title=:title WHERE trips.id=:id")
    114         assertThat(query.errors, `is`(emptyList()))
    115     }
    116 
    117     @Test
    118     fun tablePrefixInSelect_projection() {
    119         val query = SqlParser.parse("SELECT a.name, b.last_name from user a, book b")
    120         assertThat(query.errors, `is`(emptyList()))
    121         assertThat(query.tables, `is`(setOf(Table("user", "a"),
    122                 Table("book", "b"))))
    123     }
    124 
    125     @Test
    126     fun tablePrefixInSelect_where() {
    127         val query = SqlParser.parse("SELECT a.name, b.last_name from user a, book b" +
    128                 " WHERE a.name = b.name")
    129         assertThat(query.errors, `is`(emptyList()))
    130         assertThat(query.tables, `is`(setOf(Table("user", "a"),
    131                 Table("book", "b"))))
    132     }
    133 
    134     @Test
    135     fun findBindVariables() {
    136         assertVariables("select * from users")
    137         assertVariables("select * from users where name like ?", "?")
    138         assertVariables("select * from users where name like :name", ":name")
    139         assertVariables("select * from users where name like ?2", "?2")
    140         assertVariables("select * from users where name like ?2 OR name LIKE ?1", "?2", "?1")
    141         assertVariables("select * from users where name like @a", "@a")
    142         assertVariables("select * from users where name like \$a", "\$a")
    143     }
    144 
    145     @Test
    146     fun indexedVariablesError() {
    147         assertErrors("select * from users where name like ?",
    148                 ParserErrors.ANONYMOUS_BIND_ARGUMENT)
    149         assertErrors("select * from users where name like ? or last_name like ?",
    150                 ParserErrors.ANONYMOUS_BIND_ARGUMENT)
    151         assertErrors("select * from users where name like ?1",
    152                 ParserErrors.cannotUseVariableIndices("?1", 36))
    153     }
    154 
    155     @Test
    156     fun foo() {
    157         assertSections("select * from users where name like ?",
    158                 Section.text("select * from users where name like "),
    159                 Section.bindVar("?"))
    160 
    161         assertSections("select * from users where name like :name AND last_name like :lastName",
    162                 Section.text("select * from users where name like "),
    163                 Section.bindVar(":name"),
    164                 Section.text(" AND last_name like "),
    165                 Section.bindVar(":lastName"))
    166 
    167         assertSections("select * from users where name \nlike :name AND last_name like :lastName",
    168                 Section.text("select * from users where name "),
    169                 Section.newline(),
    170                 Section.text("like "),
    171                 Section.bindVar(":name"),
    172                 Section.text(" AND last_name like "),
    173                 Section.bindVar(":lastName"))
    174 
    175         assertSections("select * from users where name like :name \nAND last_name like :lastName",
    176                 Section.text("select * from users where name like "),
    177                 Section.bindVar(":name"),
    178                 Section.text(" "),
    179                 Section.newline(),
    180                 Section.text("AND last_name like "),
    181                 Section.bindVar(":lastName"))
    182 
    183         assertSections("select * from users where name like :name \nAND last_name like \n:lastName",
    184                 Section.text("select * from users where name like "),
    185                 Section.bindVar(":name"),
    186                 Section.text(" "),
    187                 Section.newline(),
    188                 Section.text("AND last_name like "),
    189                 Section.newline(),
    190                 Section.bindVar(":lastName"))
    191     }
    192 
    193     fun assertVariables(query: String, vararg expected: String) {
    194         assertThat((SqlParser.parse(query)).inputs.map { it.text }, `is`(expected.toList()))
    195     }
    196 
    197     fun assertErrors(query: String, vararg errors: String) {
    198         assertThat((SqlParser.parse(query)).errors, `is`(errors.toList()))
    199     }
    200 
    201     fun assertSections(query: String, vararg sections: Section) {
    202         assertThat(SqlParser.parse(query).sections, `is`(sections.toList()))
    203     }
    204 }
    205