/* * Copyright (C) 2020 Xizhi Zhu * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package me.xizzhu.android.ask.db sealed class Condition(internal val text: String) { object NoOp : Condition("") class IsNull(key: String) : Condition("$key IS NULL") class IsNotNull(key: String) : Condition("$key IS NOT NULL") class Equal(key: String, value: T) : Condition("$key = '${value.toString().escape()}'") class NotEqual(key: String, value: T) : Condition("$key != '${value.toString().escape()}'") class Less(key: String, value: T) : Condition("$key < ${value.toString()}") class LessOrEqual(key: String, value: T) : Condition("$key <= ${value.toString()}") class Greater(key: String, value: T) : Condition("$key > ${value.toString()}") class GreaterOrEqual(key: String, value: T) : Condition("$key >= ${value.toString()}") class Between(key: String, from: T, to: T) : Condition("$key BETWEEN ${from.toString()} AND ${to.toString()}") class Like(key: String, pattern: String) : Condition("$key LIKE '${pattern.escape()}'") class NotLike(key: String, pattern: String) : Condition("$key NOT LIKE '${pattern.escape()}'") class Glob(key: String, pattern: String) : Condition("$key GLOB '${pattern.escape()}'") class InList(key: String, values: Iterable) : Condition("$key IN (${values.toSqlInExpression()})") class NotInList(key: String, values: Iterable) : Condition("$key NOT IN (${values.toSqlInExpression()})") class And(exp1: Condition, exp2: Condition) : Condition("${exp1.text} AND ${exp2.text}") class Or(exp1: Condition, exp2: Condition) : Condition("${exp1.text} OR ${exp2.text}") class Not(exp: Condition) : Condition("NOT ${exp.text}") } object ConditionBuilder { fun noOp(): Condition.NoOp = Condition.NoOp fun String.isNull(): Condition.IsNull = Condition.IsNull(this) fun String.isNotNull(): Condition.IsNotNull = Condition.IsNotNull(this) infix fun String.eq(value: T): Condition.Equal = Condition.Equal(this, value) infix fun String.neq(value: T): Condition.NotEqual = Condition.NotEqual(this, value) infix fun String.less(value: T): Condition.Less = Condition.Less(this, value) infix fun String.lessEq(value: T): Condition.LessOrEqual = Condition.LessOrEqual(this, value) infix fun String.greater(value: T): Condition.Greater = Condition.Greater(this, value) infix fun String.greaterEq(value: T): Condition.GreaterOrEqual = Condition.GreaterOrEqual(this, value) fun String.between(from: T, to: T): Condition.Between = Condition.Between(this, from, to) infix fun String.like(pattern: String): Condition.Like = Condition.Like(this, pattern) infix fun String.notLike(pattern: String): Condition.NotLike = Condition.NotLike(this, pattern) infix fun String.glob(pattern: String): Condition.Glob = Condition.Glob(this, pattern) infix fun String.inList(values: Iterable): Condition.InList = Condition.InList(this, values) infix fun String.notInList(values: Iterable): Condition.NotInList = Condition.NotInList(this, values) infix fun Condition.and(another: Condition): Condition = Condition.And(this, another) infix fun Condition.or(another: Condition): Condition = Condition.Or(this, another) fun not(condition: Condition): Condition = Condition.Not(condition) }