项目作者: AniTrend

项目描述 :
A simple SQLite spec compliant query builder that integrates with room to create raw queries
高级语言: Kotlin
项目地址: git://github.com/AniTrend/support-query-builder.git
创建时间: 2021-03-05T06:54:05Z
项目社区:https://github.com/AniTrend/support-query-builder

开源协议:Apache License 2.0

下载


support-query-builder Run unit tests Codacy Badge FOSSA Status

A simple yet comprehensive sql select query builder with featuring an annotation processor to generate schema objects from Room annotations that plugs straight into RawQuery

Why This Project Exists?

While Room offers an excelent service loader based approach to generate an ORM layer for android application through static annotated queries, if you need to have some form of dynamic queries that might be user generated at runtime you would have to consider using SupportSQLiteQueryBuilder to generate dynamic queries. However the SupportSQLiteQueryBuilder API does a great job of constructing fairly simple queries, but lacks a fluent builder style API with joins, unions and large chains. In addition to this you have to write out table and column names as plain strings which is not only cumbersome but also error prone and adds additional overhead as you’d have to make sure that any changes you make to the entity related names are reflected throughout all your query builder references.

support-query-builder aims to solve these problems and comes in the form of 3 libraries with the following features:

  • annotations - Annotation only which is used to inform the processor of entities to inspect
  • core - The main query builder library for constructing queries
  • core-ext - Contains helper extention functions for the core modules, specifically asSupportSQLiteQuery
  • processor - Kotlin annotation proccessor that generates kotlin object classes that mirror your Room entity annotations supporting inspection @Entity, @ColumnInfo and @Embedded

See a list of changes from releases

Inspired by QueryBuilder

FOSSA Status


How Everything Works

Getting Started

  • Add the JitPack repository to your build file
  1. allprojects {
  2. repositories {
  3. ...
  4. maven { url 'https://www.jitpack.io' }
  5. }
  6. }
  • Add the dependency
  1. dependencies {
  2. implementation 'com.github.anitrend:support-query-builder:module_name:{latest_version}'
  3. }

Examples

In all the instances you need to build a query you have to create an instance of the query builder:

  1. import co.anitrend.support.query.builder.core.QueryBuilder
  2. val builder = QueryBuilder()

Submitting your query builder into a RawQuery dao method for room to consume simply call:

  1. val builder = QueryBuilder()
  2. // ... statements here
  3. builder.asSupportSQLiteQuery()

N.B. Most of the builder extension functions are infix, please see the co.anitrend.support.query.builder.dsl.* package for more details and co.anitrend.support.query.builder.core test directory for a list of different examples

Annotation processor

If you want to have your entity classes inspected and generate schema objects add the following to yout module gradle file

  1. dependencies {
  2. implementation 'com.github.anitrend:support-query-builder:annotaion:{latest_version}'
  3. kapt 'com.github.anitrend:support-query-builder:processor:{latest_version}'
  4. }

After you can annotate your entity classes with @EnititySchema as shown below, which should only be on your top level entity e.g.:

  1. @EntitySchema
  2. @Entity(tableName = "pet")
  3. internal data class PetEntity(
  4. @PrimaryKey(autoGenerate = true)
  5. @ColumnInfo(name = "id") val id: Long,
  6. @ColumnInfo(name = "name") val name: String,
  7. @ColumnInfo(name = "owner_id") val owner: Long,
  8. @Embedded(prefix = "breed_") val breed: Breed,
  9. ) {
  10. data class Breed(
  11. @ColumnInfo(name = "group") val group: String,
  12. @ColumnInfo(name = "origin") val origin: String
  13. )
  14. // This should not be generated since it is not referenced in the entity
  15. data class SomeConstruct(
  16. @ColumnInfo(name = "id") val id: Long,
  17. @Embedded(prefix = "prob_") val property: Property
  18. ) {
  19. data class Property(
  20. @ColumnInfo(name = "option_a") val optionA: String
  21. )
  22. }
  23. }

When your build completes your should be able to access a generated object called PetEntitySchema which would have the following format.

  1. public object PetEntitySchema {
  2. public const val tableName: String = "pet"
  3. public const val id: String = "id"
  4. public const val name: String = "name"
  5. public const val owner: String = "owner_id"
  6. public const val breedGroup: String = "breed_group"
  7. public const val breedOrigin: String = "breed_origin"
  8. }

You may use the newly created schema object when building out your queries

N.B. If you do not set the tableName protery on @Entity then the class name is used instead, the same applies to name property on @ColumnInfo and prefix on @Embedded
Check out the sample project and tests located in the core module for more samples

Basic statement

  1. SELECT * FROM table_name
  1. val builder = QueryBuilder()
  2. builder select "*" from "table_name"

Which can also be written as

  1. val builder = QueryBuilder()
  2. builder from "table_name"

Basic statement with alias

  1. SELECT column_name AS t FROM table_name
  1. val builder = QueryBuilder()
  2. val column = "column_name".asColumn()
  3. builder select (column `as` "t") from "table_name"

Which can also be applied on the table name

  1. SELECT * FROM table_name AS n
  1. val builder = QueryBuilder()
  2. builder from ("table_name".asTable() `as` "n")

Basic statement with where clause

  1. SELECT * FROM table_name WHERE column_name = 'something'
  1. val builder = QueryBuilder()
  2. val column = "column_name".asColumn()
  3. builder from table where {
  4. column equal "something"
  5. }

Which can also be written as

  1. val builder = QueryBuilder()
  2. val column = "column_name".asColumn()
  3. builder.from(table).where(column.equal("something"))

Statement with inner join clause

  1. SELECT * FROM table_name INNER JOIN other_table_name ON other_column_id = column_id
  1. val builder = QueryBuilder()
  2. builder from table.innerJoin("other_table_name") {
  3. on("other_column_id", "column_id")
  4. }

Which can also be written as

  1. val builder = QueryBuilder()
  2. builder.from(table.innerJoin("other_table_name").on("other_column_id", "column_id"))

Statement with inner join and where clause and order by

  1. SELECT * FROM table_name INNER JOIN other_table_name ON other_column_id = column_id WHERE column_name = 'something'
  1. val builder = QueryBuilder()
  2. val column = "column_name".asColumn()
  3. // You can ommit the `.asTable` if you want
  4. builder from table.innerJoin("other_table_name".asTable()) {
  5. on("other_column_id", "column_id")
  6. } where {
  7. column equal "something"
  8. } orderByDesc column

Statement with inner join and where clause and filter

  1. SELECT * FROM table_name INNER JOIN other_table_name ON other_column_id = column_id WHERE (column_name = 'something' AND column_name LIKE '%pe')
  1. val builder = QueryBuilder()
  2. val column = "column_name".asColumn()
  3. builder from {
  4. table.innerJoin("other_table_name").on(
  5. "other_column_id", "column_id"
  6. )
  7. } where {
  8. column.equal("something") and column.endsWith("pe")
  9. }

Statement with multiple join and where clause and filter

  1. SELECT * FROM table_name INNER JOIN other_table_name ON other_column_id = column_id LEFT JOIN some_table_name ON some_other_column_id = column_id WHERE (column_name = 'something' AND column_name LIKE '%pe')

```kotlin
val builder = QueryBuilder()
val column = “column_name”.asColumn()
builder from {
table.innerJoin(“other_table_name”).on(
“other_column_id”, “column_id”
)
.leftJoin(“some_table_name”).
on(“some_other_column_id”, “column_id”)

} where {
(column equal “something”) and (column endsWith “pe”)
}

  1. Which can also be written as:
  2. ```kotlin
  3. builder from table
  4. builder from {
  5. innerJoin("other_table_name") {
  6. on("other_column_id", "column_id")
  7. }
  8. }
  9. builder from {
  10. leftJoin("some_table_name").on(
  11. "some_other_column_id", "column_id"
  12. )
  13. }
  14. builder where {
  15. (column equal "something") and (column endsWith "pe")
  16. }

License

  1. Copyright 2021 AniTrend
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.