This is an experimental project to build a modern SQL alternative called Sigma.
Sigma tries to combine the power of relational calculus and common programming languages.
cargo run
This will run an interactive shell like this:
Sigma 0.0.1
>>>
Then input some expressions and see what happens!
There is a built-in json module. You can load some json file and process it with Sigma:
>>> import json
>>> list = json.load("path/to/file.json")
Syntax:
Expression [';'] |
'import' Name [';'] |
CreateClass |
DeleteClass
Syntax:
'create' 'class' Name '{'
(Name ':' TypeName ',')*
['id' Name (',' Name)*]
'}'
TypeName = 'bool' | 'i64' | 'f64' | 'text'
Example:
create class User { name: text, score: i64, id name }
You must specify the id fields for a class. The type of id fields can only be i64
or text
for now.
In this example, the "name" field will be used as the id of the class.
By default, if the id is not specified, a field name "id" will be used as the id. For example:
create class User { id: text, score: i64 }
In this case the "id" field will be used as the id of the class.
After a class is created, the name of the class will represent a set of instances of that class. Then you can manipulate the class set like other collections:
>>> create class User { name: text, score: i64, id name }
>>> into User insert { name: "a", score: 1 }, { name: "b", score: 2 }
2
>>> from u in User select u.score
[2, 1]
>>> from u in User update u.score *= 2
2
>>> User
{
{name: "a", score: 2}
{name: "b", score: 4}
}
Syntax:
'delete' 'class' Name
Sigma is a strongly-typed scripting language. There is no implicit type conversions. For example, you can not add an integer with a boolean or a floating-point number.
TODO
A boolean expression consists of one of the keywords true
or false
.
An integer literal should match the regular expression [0-9]+
.
For now, integer literal will be evaluated to 64bit signed integers at runtime.
Example:
>>> 123
123
A floatint-point literal should match the regular expression [0-9]+\.[0-9]+([eE][+-]?[0-9]+)?
.
For now, floating-point literals will be evaluated to 64bit double-precision floating-point numbers at runtime.
Example:
>>> 1.2
1.2
TODO
A string literal should match the regular expression "([^"\\]|\\.)*"
.
>>> "abc"
"abc"
>>> "ab\"cd\n"
"ab\"cd\n"
Syntax:
Expression '+' Expression |
Expression '-' Expression |
Expression '*' Expression |
Expression '/' Expression |
Expression '%' Expression |
Expression '|' Expression |
Expression '^' Expression |
Expression '&' Expression |
Example:
>>> 1 + 2
3
>>> true | false
true
>>> true & false
false
Syntax:
'!' Expression |
'-' Expression
Example:
>>> !true
false
>>> -1234
-1234
Syntax:
Expression '==' Expression |
Expression '!=' Expression |
Expression '<' Expression |
Expression '<=' Expression |
Expression '>' Expression |
Expression '>=' Expression |
Expression 'in' Expression |
Expression 'not' 'in' Expression
Example:
>>> 1 == 1
true
>>> 1 != 1
false
>>> 1 in [1, 2]
true
>>> 1 not in [1, 2]
false
List is a ordered sequence of objects.
Syntax:
'[' (Expression ',')* Expression? ']'
Example:
>>> []
[]
>>> [1, 2 + 3]
[1, 5]
>>> [1, 2, 3,]
[1, 2, 3]
Syntax:
Expression '[' Expression ']'
Example:
>>> [1, 2, 3][0]
1
Hash is a set of unordered name/value pairs. Hash field name can be an identifier or a string.
Syntax:
'{' (Name ':' Expression ',')* (Name ':' Expression)? '}'
Example:
>>> {}
{}
>>> {a: 1 + 1, b: "2"}
{a: 2, b: "2"}
>>> {foo: "foo", "foo bar": "foo bar"}
{foo: "foo", foo bar: "foo bar"}
Syntax:
Expression '.' Name
Example:
>>> x = {foo: "bar", "foo bar": "foo bar"}
>>> x.foo
"bar"
>>> x."foo bar"
"foo bar"
Syntax:
Expression '=' Expression
>>> a = [1, 2]
>>> a[0] = 2
>>> a
[2, 2]
>>> b = {x: 1, y: 1}
>>> b.x = 2
>>> b
{x: 2, y: 1}
There is two kinds of collection for now: list and class.
Syntax:
'into' Expression 'insert' (Expression ',')* Expression ','?
Example:
>>> list = [1, 2]
>>> into list insert 3, 4
2
>>> list
>>> [1, 2, 3, 4]
Syntax:
'from' Name 'in' Expression ['where' Expression] 'update' Expression
Example:
>>> list = [1, 2, 3]
>>> from x in list update x *= 2
3
>>> list
[2, 4, 6]
>>> from x in list where x == 4 update x += 1
1
>>> list
[2, 5, 6]
Syntax:
'from' Name 'in' Expression ['where' Expression] 'delete' Name
Example:
>>> list = [{a: 1, b: 2}, {a: 3, b: 4}]
>>> from x in list delete x
2
>>> list
[]
>>> list = [{a: 1, b: 2}, {a: 3, b: 4}]
>>> from x in list where x.a < 2 delete x
1
>>> list
[{a: 3, b: 4}]
Syntax:
'from' Name 'in' Expression
['join' Name 'in' Expression ['on' Expression]]
['where' Expression]
['limit' Expression]
['select' Expression]
Example:
>>> list = from x in [1, 2, 3, 4] select { a: x, b: x * 2 }
[{a: 1, b: 2}, {a: 2, b: 4}, {a: 3, b: 6}, {a: 4, b: 8}]
>>> from x in list where x.a < 4
[{a: 1, b: 2}, {a: 2, b: 4}, {a: 3, b: 6}]
>>> from x in list where x.a < 4 limit 1
[{a: 1, b: 2}]
>>> from x in list where x.a < 4 limit 1..
[{a: 2, b: 4}, {a: 3, b: 6}]
>>> from x in list where x.a < 4 limit 1..2
[{a: 2, b: 4}]
>>> from x in list select x.a
[1, 2, 3, 4]
>>> from x in list where x.a < 4 limit 2 select { a: x.a, c: x.a + x.b }
[{a: 1, c: 3}, {a: 2, c: 6}]
>>> list2 = from x in [3, 4, 5, 6] select { a: x, c: x * 3 }
[{a: 3, c: 9}, {a: 4, c: 12}, {a: 5, c: 15}, {a: 6, c: 18}]
>>> from x1 in list join x2 in list2 on x1.a == x2.a
[{x1: {a: 3, b: 6}, x2: {a: 3, c: 9}}, {x1: {a: 4, b: 8}, x2: {a: 4, c: 12}}]
>>> from x1 in list join x2 in list2 on x1.a == x2.a where x1.a % 2 == 0 select { a: x1.a, b: x1.b, c: x2.c }
[{a: 4, b: 8, c: 12}]
Nested expressions are also possible:
>>> ids = [1, 2, 3, 4]
[1, 2, 3, 4]
>>> list = from x in ids select { a: x, b: ids }
[{a: 1, b: [1, 2, 3, 4]}, {a: 2, b: [1, 2, 3, 4]}, {a: 3, b: [1, 2, 3, 4]}, {a: 4, b: [1, 2, 3, 4]}]
>>> from x in list where x.a % 2 == 0 select { a: x.a, b: from i in x.b where i % 2 == 0 }
[{a: 2, b: [2, 4]}, {a: 4, b: [2, 4]}]