Appearance
kd: the scripting language
kd is the scripting language of kinedb. A kd script runs in three places:
- A file:
kinedb --data-dir ./data -f script.kdruns the script in the process, with no server. - A stored function:
CREATE FUNCTION ... LANGUAGE kdstores a function in the database, andCALLruns it on the server. - A ticker:
CREATE TICKER ... CALL <function>runs a stored function on a schedule.
Every kd value is a JSON value: a number, a string, a boolean, null, an array or an object. Every example on this page ran on the current build with -f, in the order of this page, in one database. A // expect: comment shows a part of the output.
Run a script
sh
kinedb --data-dir ./data -f script.kdprint(...) writes its arguments on one line, with a space between them. After the last statement, kinedb prints the value of that statement: a string as it is, any other value as JSON, and nothing for null.
kd
// expect: hello kd 42
print("hello", "kd", 42);Values
typeof gives the type of a value. A string takes double or single quotes, and the escapes \n, \t, \r, \\, \' and \".
kd
// expect: number string bool null array object
print(typeof(1), typeof("a"), typeof(true), typeof(null), typeof([1]), typeof({a: 1}));Variables
let declares a variable. =, += and -= assign to it.
kd
// expect: 35
let x = 10;
x = 30;
x += 10;
x -= 5;
print(x);Operators
The arithmetic operators are +, -, *, / and %. *, / and % bind stronger than + and -, and parentheses group.
kd
// expect: 17 2 1 2.5 25
print(2 + 3 * 5, 17 % 5, 7 - 6, 5 / 2, (2 + 3) * 5);+ also joins strings and arrays:
kd
// expect: hello world [1,2,3,4]
print("hello" + " " + "world", [1, 2] + [3, 4]);The comparison operators are ==, !=, <, <=, > and >=. The logical operators are &&, || and !.
kd
// expect: true true false true
print(1 == 1.0, "a" != "b", true && false, !false || false);In a condition, null, false, 0 and "" are false. Every other value is true, empty arrays and empty objects too.
kd
// expect: no no no no yes yes
let out = "";
for v in [null, false, 0, "", [], {}] {
if v { out = out + "yes "; } else { out = out + "no "; }
}
print(out);Arrays and objects
An index reads an array element (from 0) or an object field. A dot also reads a field. An assignment to an index or a field changes the value.
kd
// expect: 2 Alice
let a = [1, 2, 3];
let p = {name: "Alice", age: 30};
print(a[1], p.name);kd
// expect: [1,99,3] 31
let a = [1, 2, 3];
a[1] = 99;
let p = {name: "Alice", age: 30};
p.age = 31;
print(a, p["age"]);Control flow
if, else if and else take a condition without parentheses and a block in braces.
kd
// expect: medium
let n = 15;
if n > 20 { print("large"); } else if n > 10 { print("medium"); } else { print("small"); }for <name> in <value> walks the elements of an array, or the keys of an object. continue goes to the next element, and break leaves the loop.
kd
// expect: 7
let sum = 0;
for x in [1, 2, 3, 4, 5, 6] {
if x == 3 { continue; }
if x == 5 { break; }
sum += x;
}
print(sum);kd
// expect: a=1 b=2
let o = {a: 1, b: 2};
let s = "";
for k in o { s = s + k + "=" + to_string(o[k]) + " "; }
print(s);Functions
fn defines a function. return gives its result; a function without return gives null. A function can call itself.
kd
// expect: 120
fn fact(n) {
if n <= 1 { return 1; }
return n * fact(n - 1);
}
print(fact(5));Comments
kd
// expect: 3
// a line comment
/* a block
comment */
print(1 + 2);Built-in functions
| Function | What it gives |
|---|---|
print(a, b, ...) | Writes the values on one line. Gives null. |
typeof(v) | "number", "string", "bool", "null", "array" or "object". |
length(v) | The number of characters of a string, or of elements of an array or an object. |
keys(o), values(o) | The keys, or the values, of an object, as an array. |
to_string(v) | The value as a string. |
to_number(s) | The string as a number, or null when it is not a number. |
to_int(n) | The number without its fraction. |
floor(n), ceil(n), round(n) | The number rounded down, up, or to the nearest integer. |
kd
// expect: 3 5 ["a","b"] [1,2]
print(length([1, 2, 3]), length("hello"), keys({a: 1, b: 2}), values({a: 1, b: 2}));kd
// expect: 42 42 3 3 -4 4 4
print(to_number("42"), to_string(42), to_int(3.7), floor(3.9), floor(-3.2), ceil(3.1), round(3.5));The database
A script reads and writes the database with these functions. The same functions work in a file (-f) and in a stored function.
| Function | What it does |
|---|---|
query(sql) | Runs the SQL. A SELECT gives an array of objects, one per row. |
find(name), find(name, where) | SELECT * FROM <name>, with an optional WHERE <where>. |
insert(name, object) | INSERT INTO <name>, with the keys of the object as the columns. |
update(name, object, where) | UPDATE <name> SET <key> = <value>, ... WHERE <where>. |
delete(name, where), remove(name, where) | DELETE FROM <name>, with an optional WHERE <where>. |
log(a, b, ...) | Writes the values to the log output. |
The examples use this table:
sql
CREATE TABLE players (id INT, name TEXT, score INT, PRIMARY KEY (id));
INSERT INTO players (id, name, score) VALUES (1, 'ann', 10), (2, 'bob', 20);kd
// expect: 2 ann 20
let rows = query("SELECT name, score FROM players ORDER BY id");
print(length(rows), rows[0].name, rows[1].score);kd
// expect: [{"id":2,"name":"bob","score":20},{"id":3,"name":"cid","score":30}]
insert("players", {id: 3, name: "cid", score: 30});
print(find("players", "score > 15"));kd
// expect: 99 2
update("players", {score: 99}, "id = 1");
delete("players", "id = 2");
print(query("SELECT score FROM players WHERE id = 1")[0].score, length(find("players")));The last statement of this script is a value, so kinedb prints it:
kd
// expect: 129
let total = 0;
for r in find("players") { total += r.score; }
totalStored functions and tickers
CREATE FUNCTION <name>(<parameters>) [RETURNS VALUE | TABLE] LANGUAGE kd AS $$ <body> $$ stores a function, and CALL <name>(<arguments>) runs it. The arguments bind to the parameter names in order, and a parameter without an argument is null. The array args also holds all the arguments. The body uses the built-in functions and the database functions above. Stored functions, CALL and tickers need a server connection.
sql
CREATE FUNCTION add_points(player, points) RETURNS VALUE LANGUAGE kd AS $$ update("players", {score: points}, "id = " + to_string(player)); return points; $$;
CALL add_points(1, 50);
CREATE FUNCTION decay() RETURNS VALUE LANGUAGE kd AS $$ query("UPDATE players SET score = score - 1"); return null; $$;
CREATE TICKER decay_every_minute EVERY 60s CALL decay OVERLAP SKIP;See the SQL reference for SHOW FUNCTIONS, DROP FUNCTION and the ticker statements.