196 lines
6.8 KiB
GDScript
196 lines
6.8 KiB
GDScript
@tool
|
|
extends RefCounted
|
|
class_name Condition
|
|
## A programatically way to define Conditions.
|
|
##
|
|
## Condition is a way to define SQL Statements to be used with GDataORM. You can create
|
|
## full SQL Statements, or Simple conditions to be used when fetching data from the [SQLite]
|
|
## database.[br][br]
|
|
##
|
|
## [b]Example:[/b]
|
|
## [codeblock]
|
|
## var fetch_like_mar: Condition = Condition.new().select("*").from("my_table").where() \
|
|
## .like("name", "Mar%")
|
|
## var fetch_gold: Condition = Condition.new().select(["gold"]).from("inventories").where() \
|
|
## .greater("gold",0)
|
|
## var low_health: Condition = Condition.new().lesser("health",5)
|
|
## var mid_health: Condition = Condition.new().between("health",25,75)
|
|
## var full_health: Condition = Condition.new().greater_equal("health",100)
|
|
## [/codeblock]
|
|
|
|
enum _CT {
|
|
NOT,
|
|
EQUAL,
|
|
LESS_THAN,
|
|
GREATER_THAN,
|
|
LESS_THAN_EQUAL,
|
|
GREATER_THAN_EQUAL,
|
|
AND,
|
|
BETWEEN,
|
|
IN,
|
|
LIKE,
|
|
OR,
|
|
SELECT,
|
|
FROM,
|
|
WHERE,
|
|
}
|
|
|
|
var _conditions: Array = []
|
|
|
|
func _single_op(op: _CT) -> Dictionary:
|
|
return {"type": op}
|
|
|
|
func _param_op(op: _CT, param: Variant) -> Dictionary:
|
|
return {"type": op, "param": param}
|
|
|
|
func _comparison_op(op: _CT, column: Variant, value: Variant) -> Dictionary:
|
|
return {"type": op, "column": column, "value": value}
|
|
|
|
## Binary operator to invert true and false in a statement.
|
|
func is_not() -> Condition:
|
|
_conditions.append(_single_op(_CT.NOT))
|
|
return self
|
|
|
|
## Evaluates the equality of a [param column] value and the [param value] given.
|
|
func equal(column: String, value: Variant) -> Condition:
|
|
_conditions.append(_comparison_op(_CT.EQUAL, column, value))
|
|
return self
|
|
|
|
## Evaluates the [param column] value to be lesser than [param value] given.
|
|
func lesser(column: String, value: Variant) -> Condition:
|
|
_conditions.append(_comparison_op(_CT.LESS_THAN, column, value))
|
|
return self
|
|
|
|
## Evaluates the [param column] value to be greater than [param value] given.
|
|
func greater(column: String, value: Variant) -> Condition:
|
|
_conditions.append(_comparison_op(_CT.GREATER_THAN, column, value))
|
|
return self
|
|
|
|
## Evaluates the [param column] value to be lesser than or equal to [param value] given.
|
|
func lesser_equal(column: String, value: Variant) -> Condition:
|
|
_conditions.append(_comparison_op(_CT.LESS_THAN_EQUAL, column, value))
|
|
return self
|
|
|
|
## Evaluates the [param column] value to be greater than or equal to [param value] given.
|
|
func greater_equal(column: String, value: Variant) -> Condition:
|
|
_conditions.append(_comparison_op(_CT.GREATER_THAN_EQUAL, column, value))
|
|
return self
|
|
|
|
## Binary operator for AND'ing two evaluation values together.
|
|
func also() -> Condition:
|
|
_conditions.append(_single_op(_CT.AND))
|
|
return self
|
|
|
|
## Evaluates the [param column] value to be between [param lower]'s value and [param upper]'s value.
|
|
func between(column: String, lower: Variant, upper: Variant) -> Condition:
|
|
_conditions.append(_comparison_op(_CT.BETWEEN, column, [lower, upper]))
|
|
return self
|
|
|
|
## Evaluates the [param column] to see if [param value] is included in it. You can pass an array
|
|
## of values to this, or use a [Condition] to fetch data from another table.
|
|
func includes(column: String, value: Variant) -> Condition:
|
|
_conditions.append(_comparison_op(_CT.IN, column, value))
|
|
return self
|
|
|
|
## Evaluates the [param column] to see if [param value] matches the given string. This utilizes
|
|
## [SQLite]'s LIKE statement, which means that you can use wildcard operators '%' and '_' in the
|
|
## pattern string.[br][br]
|
|
## [b]Wildcard Patterns:[/b][br]
|
|
## - '%' match any 1 or more characters in a pattern, EG: "Mar%" will return "Mario", "Mark", "Margin" etc etc.[br]
|
|
## - '_' match only 1 wildcard character before moving to the next. EG: "h_nt" will return "hunt", "hint", or
|
|
## "__pple" will return "topple", "supple", "tipple"[br]
|
|
## [b][color=red]NOTE:[/color][/b] [SQLite]'s engine is case-insensitive, so [code]"A" LIKE "a"[/code] will return true, but
|
|
## unicode characters that are not in the ASCII range are case-sensitive, so [code]"Ä" LIKE "ä"[/code] will return false.
|
|
func like(column: String, value: Variant) -> Condition:
|
|
_conditions.append(_comparison_op(_CT.LIKE, column, value))
|
|
return self
|
|
|
|
## Binary operator for OR'ing two evaluations together.
|
|
func otherwise() -> Condition:
|
|
_conditions.append(_single_op(_CT.OR))
|
|
return self
|
|
|
|
## Statement, fetches [param columns] from a table during execution. [param columns] can be a string value of "*" or "column1, column2, column3" or an
|
|
## array of strings such as ["column1","column2","column3"].
|
|
func select(columns: Variant) -> Condition:
|
|
_conditions.append(_param_op(_CT.SELECT, columns))
|
|
return self
|
|
|
|
## Statement Modifier, used in conjunction with [method Condition.select] to define which table the data is to be fetched from.
|
|
func from(table: String) -> Condition:
|
|
_conditions.append(_param_op(_CT.FROM, table))
|
|
return self
|
|
|
|
## Statement Modifier, defines the conditions that must match in order to fetch data from the table.
|
|
func where() -> Condition:
|
|
_conditions.append(_single_op(_CT.WHERE))
|
|
return self
|
|
|
|
func _to_string() -> String:
|
|
var str = ""
|
|
var pos := 0
|
|
|
|
for cond in _conditions:
|
|
match cond.type:
|
|
#NOTE Single Operation _single_op()
|
|
_CT.NOT:
|
|
if _conditions[pos+1].type == _CT.BETWEEN:
|
|
pos += 1
|
|
continue
|
|
str += "NOT "
|
|
_CT.AND:
|
|
str += "AND "
|
|
_CT.OR:
|
|
str += "OR "
|
|
_CT.WHERE:
|
|
str += "WHERE "
|
|
|
|
#NOTE Param Operation _param_op()
|
|
_CT.SELECT:
|
|
var param = ""
|
|
if cond.param is Array:
|
|
param = ", ".join(cond.param)
|
|
elif cond.param is String:
|
|
param = cond.param
|
|
else:
|
|
assert(false, "SELECT statement only takes a String or Array parameters.")
|
|
str += "SELECT %s " % param
|
|
_CT.FROM:
|
|
str += "FROM %s " % cond.param
|
|
|
|
#NOTE Comparison Operation _comparison_op()
|
|
_CT.EQUAL:
|
|
if typeof(cond.value) == TYPE_STRING:
|
|
str += "%s = '%s'" % [cond.column, cond.value]
|
|
else:
|
|
str += "%s = %s " % [cond.column, cond.value]
|
|
_CT.LESS_THAN:
|
|
str += "%s < %s " % [cond.column, cond.value]
|
|
_CT.GREATER_THAN:
|
|
str += "%s > %s " % [cond.column, cond.value]
|
|
_CT.LESS_THAN_EQUAL:
|
|
str += "%s <= %s " % [cond.column, cond.value]
|
|
_CT.GREATER_THAN_EQUAL:
|
|
str += "%s >= %s " % [cond.column, cond.value]
|
|
_CT.BETWEEN:
|
|
if _conditions[pos-1].type == _CT.NOT:
|
|
str += "%s NOT BETWEEN " % cond.column
|
|
else:
|
|
str += "%s BETWEEN " % cond.column
|
|
str += "%s and %s" % cond.value
|
|
_CT.IN:
|
|
if _conditions[pos-1].type == _CT.NOT:
|
|
str += "%s NOT IN " % cond.column
|
|
else:
|
|
str += "%s IN " % cond.column
|
|
if cond.value is Condition:
|
|
str += "(%s) " % cond.value.to_string()
|
|
elif cond.value is Array:
|
|
str += "(%s) " % ", ".join(cond.value)
|
|
else:
|
|
assert(false, "IN only takes Array of values or a Condition")
|
|
_CT.LIKE:
|
|
str += "%s LIKE '%s' " % [cond.column, cond.value]
|
|
pos += 1
|
|
|
|
return str.strip_edges()
|