diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
index b4015ed5b8d..e58e59209f6 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
@@ -42,105 +42,113 @@
query_log = "[key_name(usr)] [query_log]"
log_admin(query_log)
- for(var/list/query_tree in querys)
- var/list/from_objs = list()
- var/list/select_types = list()
+ try
+ for(var/list/query_tree in querys)
+ var/list/from_objs = list()
+ var/list/select_types = list()
- switch(query_tree[1])
- if("explain")
- SDQL_testout(query_tree["explain"])
- return
-
- if("call")
- if("on" in query_tree)
- select_types = query_tree["on"]
- else
+ switch(query_tree[1])
+ if("explain")
+ SDQL_testout(query_tree["explain"])
return
- if("select", "delete", "update")
- select_types = query_tree[query_tree[1]]
+ if("call")
+ if("on" in query_tree)
+ select_types = query_tree["on"]
+ else
+ return
- from_objs = SDQL_from_objs(query_tree["from"])
+ if("select", "delete", "update")
+ select_types = query_tree[query_tree[1]]
- var/list/objs = list()
+ from_objs = SDQL_from_objs(query_tree["from"])
- for(var/type in select_types)
- var/char = copytext(type, 1, 2)
+ var/list/objs = list()
- if(char == "/" || char == "*")
- for(var/from in from_objs)
- objs += SDQL_get_all(type, from)
+ for(var/type in select_types)
+ var/char = copytext(type, 1, 2)
- else if(char == "'" || char == "\"")
- objs += locate(copytext(type, 2, length(type)))
+ if(char == "/" || char == "*")
+ for(var/from in from_objs)
+ objs += SDQL_get_all(type, from)
- if("where" in query_tree)
- var/objs_temp = objs
- objs = list()
- for(var/datum/d in objs_temp)
- if(SDQL_expression(d, query_tree["where"]))
- objs += d
+ else if(char == "'" || char == "\"")
+ objs += locate(copytext(type, 2, length(type)))
- switch(query_tree[1])
- if("call")
- var/list/call_list = query_tree["call"]
- var/list/args_list = query_tree["args"]
+ if("where" in query_tree)
+ var/objs_temp = objs
+ objs = list()
+ for(var/datum/d in objs_temp)
+ if(SDQL_expression(d, query_tree["where"]))
+ objs += d
- for(var/datum/d in objs)
- for(var/v in call_list)
- // To stop any procs which sleep from executing slowly.
- if(d)
- if(hascall(d, v))
- var/list/arguments[0]
- for(var/list/arg in args_list)
- arguments += SDQL_expression(d, arg)
- spawn() call(d, v)(arglist(arguments)) // Spawn in case the function sleeps.
+ switch(query_tree[1])
+ if("call")
+ var/list/call_list = query_tree["call"]
+ var/list/args_list = query_tree["args"]
- if("delete")
- for(var/datum/d in objs)
- del(d)
+ for(var/datum/d in objs)
+ for(var/v in call_list)
+ var/list/arguments[0]
+ for(var/list/arg in args_list)
+ arguments += SDQL_expression(d, arg)
- if("select")
- var/text = ""
- for(var/datum/t in objs)
- text += "\ref[t]"
- if(istype(t, /atom))
- var/atom/a = t
+ if(copytext(v, 1, 8) == "global.") // Global proc.
+ spawn()
+ call("/proc/[copytext(v, 8)]")(arglist(arguments))
+ else if(d)
+ if(hascall(d, v))
+ spawn()
+ call(d, v)(arglist(arguments)) // Spawn in case the function sleeps.
- if(a.x)
- text += ": [t] at ([a.x], [a.y], [a.z])
"
+ if("delete")
+ for(var/datum/d in objs)
+ del(d)
- else if(a.loc && a.loc.x)
- text += ": [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])
"
+ if("select")
+ var/text = ""
+ for(var/datum/t in objs)
+ text += "\ref[t]"
+ if(istype(t, /atom))
+ var/atom/a = t
+
+ if(a.x)
+ text += ": [t] at ([a.x], [a.y], [a.z])
"
+
+ else if(a.loc && a.loc.x)
+ text += ": [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])
"
+
+ else
+ text += ": [t]
"
else
text += ": [t]
"
- else
- text += ": [t]
"
+ usr << browse(text, "window=SDQL-result")
- usr << browse(text, "window=SDQL-result")
+ if("update")
+ if("set" in query_tree)
+ var/list/set_list = query_tree["set"]
+ for(var/datum/d in objs)
+ var/list/vals = list()
+ for(var/v in set_list)
+ if(v in d.vars)
+ vals += v
+ vals[v] = SDQL_expression(d, set_list[v])
- if("update")
- if("set" in query_tree)
- var/list/set_list = query_tree["set"]
- for(var/datum/d in objs)
- var/list/vals = list()
- for(var/v in set_list)
- if(v in d.vars)
- vals += v
- vals[v] = SDQL_expression(d, set_list[v])
+ if(istype(d, /turf))
+ for(var/v in vals)
+ if(v == "x" || v == "y" || v == "z")
+ continue
- if(istype(d, /turf))
- for(var/v in vals)
- if(v == "x" || v == "y" || v == "z")
- continue
+ d.vars[v] = vals[v]
- d.vars[v] = vals[v]
-
- else
- for(var/v in vals)
- d.vars[v] = vals[v]
+ else
+ for(var/v in vals)
+ d.vars[v] = vals[v]
+ catch(var/exception/e)
+ usr << "A runtime error has occured during the execution of your query and your query has been aborted."
+ usr << "[e]"
/proc/SDQL_parse(list/query_list)
var/datum/SDQL_parser/parser = new()
@@ -353,6 +361,12 @@
else if(copytext(expression[i], 1, 2) in list("'", "\""))
val = copytext(expression[i], 2, length(expression[i]))
+ else if(expression[i] == "{")
+ var/list/expressions_list = expression[++i]
+ val = list()
+ for(var/list/expression_list in expressions_list)
+ val += SDQL_expression(object, expression_list)
+
else
val = SDQL_var(object, expression, i)
i = expression.len
@@ -392,7 +406,7 @@
/proc/SDQL2_tokenize(query_text)
var/list/whitespace = list(" ", "\n", "\t")
- var/list/single = list("(", ")", ",", "+", "-", ".", ";", "\[", "\]")
+ var/list/single = list("(", ")", ",", "+", "-", ".", ";", "\[", "\]", "{", "}")
var/list/multi = list(
"=" = list("", "="),
"<" = list("", "=", ">"),
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
index e5d983b7649..f2ec46111ba 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
@@ -31,12 +31,13 @@
// expression : ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
// unary_expression : unary_operator ( unary_expression | value | '(' expression ')' )
// comparitor : '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
-// value : variable | string | number | 'null'
+// value : variable | string | array | number | 'null'
// unary_operator : '!' | '-' | '~'
// binary_operator : comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
// bool_operator : 'AND' | '&&' | 'OR' | '||'
//
// string : ''' ''' | '"' '"'
+// array : '{' [arguments] '}'
// number :
//
//////////
@@ -336,7 +337,7 @@
variable(i, list/node)
var/list/L = list(token(i))
node[++node.len] = L
-
+
if(token(i) == "\[")
L += token(i + 1)
i += 2
@@ -401,12 +402,43 @@
return i + 1
+ //array: '{' expression, expression, ... '}'
+ array(var/i, var/list/node)
+ // Arrays get turned into this: list("{", list(exp_1a = exp_1b, ...), ...), "{" is to mark the next node as an array.
+ if(copytext(token(i), 1, 2) != "{")
+ parse_error("Expected an array but found '[token(i)]'")
+ return i + 1
+
+ node += token(i) // Add the "{"
+ var/list/expression_list = list()
+
+ if(token(i + 1) != "}")
+ var/list/temp_expression_list = list()
+
+ do
+ i = expression(i + 1, temp_expression_list)
+
+ if(token(i) == ",")
+ expression_list[++expression_list.len] = temp_expression_list
+ temp_expression_list = list()
+ while(token(i) && token(i) != "}")
+
+ expression_list[++expression_list.len] = temp_expression_list
+ else
+ i++
+
+ node[++node.len] = expression_list
+ return i + 1
//call_function: ['(' [arguments] ')']
call_function(i, list/node, list/arguments)
var/list/cur_argument = list()
if(length(tokenl(i)))
- node += token(i++)
+ var/procname = ""
+ if(tokenl(i) == "global" && token(i + 1) == ".") // Global proc.
+ i += 2
+ procname = "global."
+ node += procname + token(i++)
if(token(i) != "(")
parse_error("Expected ( but found '[token(i)]'")
else if(token(i + 1) != ")")
@@ -526,11 +558,11 @@
if(token(i) == "null")
node += "null"
i++
-
+
else if(lowertext(copytext(token(i), 1, 3)) == "0x" && isnum(hex2num(copytext(token(i), 3))))
node += hex2num(copytext(token(i), 3))
i++
-
+
else if(isnum(text2num(token(i))))
node += text2num(token(i))
i++
@@ -538,6 +570,9 @@
else if(copytext(token(i), 1, 2) in list("'", "\""))
i = string(i, node)
+ else if(copytext(token(i), 1, 2) == "{") // Start a list.
+ i = array(i, node)
+
else
i = variable(i, node)