I've invented an SQL-like language. Let's call it SelectQL. You can't INSERT
anything, you can only SELECT
, and I don't have the time for an interpreter. How about you help?
The Challenge
Write a full program or a function that takes in a database of tables and a valid SelectQL SELECT
string, interprets the string, and outputs the resulting SELECT
ion.
SELECT
Specification
The SELECT
SelectQL statement is as follows (optional portions are in curly brackets):
SELECT [column] FROM [table] {WHERE ( [condition] {[AND/OR] [condition] ... } ) }
[column]
can beALL
for selecting all columns, or a valid column name in the[table]
.[table]
is the name of a table.- The
WHERE
clause is optional. AWHERE
clause is followed by a list of[condition]
separated by any ofAND
orOR
, surrounded by parentheses()
. - A
[condition]
is a key-value pair separated by an equals sign=
. [condition]
can be preceded withNOT
to select the complement of the condition.- Operator Precedence:
NOT
has higher precedence thanAND
andOR
.AND
andOR
is executed left to right. - Conditions involving arrays/lists (
{980, "abc"}
indata
below) will look for the existence of a requested value in the array, and return the whole array if true. key
must be a column in[table]
.- SelectQL query strings are case insensitive.
Table Format
Your program should take in an SelectQL database (array of arrays, list of lists, delimited string, JSON object, etc) in the following format:
[
[table name, (column names), [(row), (row), ...]],
[table name, (column names), [(row), (row), ...]]
]
table name
is the name of the table.[column names]
is a list of unique strings which are column names. These are the keys in[condition]
.- Each column's values all must have the same type.
[row]
is a list-like of values. Each row must be the same length as[column names]
.- There can be no
[row]
s. - Elements in
[row]
cannot be empty. Empty strings or arrays are not considered empty.
Types
There are three types in SelectQL: number
, string
, array
.
Numbers are at least 1 digit in 0-9
, with an optional decimal point with at least 1 digit.
Strings are double-quote-delimited sequences of characters. Empty strings are possible (""
).
Arrays are curly-bracket-delimited comma-separated sequences of numbers, strings, or arrays. Arrays can be heterogeneous. Empty arrays are possible ({}
).
Input
- A valid SelectQL database, and
- A valid SelectQL
SELECT
query. It will alwaysSELECT
a valid table in the database.
Output
- The result of the query. The result must have the columns as well as the resulting rows.
Examples
The examples will use the following database:
[
[data, (d1, d2, 3, ~!@#), [(123, "", {980, "abc"}, "false"), (456, "this isn't empty!", {{},{}}, "-123.4444"), (1, "2", {3, 4}, "five")]],
[no, (yes, a, 1.5, what), []]
]
Format:
string --> result
-----------------
"SELECT ALL FROM data"
--> [(d1, D2, 3, ~!@#), [(123, "", {980, "aBc"}, "false"), (456, "this isn't empty!", {{},{}}, "-123.4444"), (1, "2", {3, 4}, "five")]]
"SELECT D1 FROM DATA"
--> [(d1), [(123), (456), (1)]]
"SELECT d1, 3 FROM data"
--> [(d1, 3), [(123, {980, "aBc"}), (456, {{},{}}), (1, {3,4})]]
"SELECT ALL FROM DATA WHERE (NOT d1=123)"
--> [(d1, D2, 3, ~!@#), [(456, "this isn't empty!", {{},{}}, "-123.4444"), (1, "2", [3, 4], "five")]]
"SELECT all FROM data WHERE (d1=123)"
--> [(d1, D2, 3, ~!@#), [(123, "", [980, "aBc"], "false")]
"SELECT ~!@# FROM DATA WHERE (3={} OR d2="")"
--> [(~!@#), [("false"), ("-123.4444")]
"SELECT all FROM DATA WHERE (d1=2)"
--> [(d1, d2, 3, ~!@#), []]
"select all from no"
--> [(yes, a, 1.5, what), []]
"select 3 from data where (3=980)"
--> [(3),[[{980, "aBc"}]]
Additional Rules/Clarifications
- Standard loopholes are forbidden.
- Input and output can be in any reasonable format.
- Please explain your answers.
- This is code-golf, so the program with the smallest number of bytes wins!
AND
andOR
be mixed together? If so, what is their precedence? \$\endgroup\$A=1 AND B=2 OR C=3 AND D=4
is((A==1 and B==2) or C==3) and D==4
\$\endgroup\$column = value
checks? \$\endgroup\$[123, "", [980, "abc"], "false"]
, mean, in particular, the third value. How does that work with the=
operator? \$\endgroup\$