cmd — Command & SQL Templates
The cmd template type models named command invocations — SQL queries, shell commands, HTTP requests, or any parameterised operation. At generation time, Generator.generate() dispatches to the appropriate generator (SqlGen, BashGen, and so on).
Syntax
A cmd template body contains either a bare identifier (naming the command type) or a call expression (naming the operation and its arguments). Bare form — the command type is a single word. The template parameters become the command's parameters.
cmd [sql] rawQuery(sql: String) {
sql
}
Call form — the command is a named operation with typed arguments. Arguments can reference template parameters with $${ }.
cmd [sql] findUser(email: String) {
SELECT(
table: users,
cols: "id, name, email",
where: "email = '$${email}'"
)
}
cmd [sql] createUser(name: String, email: String) {
INSERT(
table: users,
cols: "name, email",
values: "'$${name}', '$${email}'"
)
}
Generating SQL
Call Generator.generate() to produce the SQL string. The SqlGen generator handles all standard SQL operations.
use TLang.Generator
cmd [sql] allUsers() {
SELECT(table: users)
}
cmd [sql] userById(id: String) {
SELECT(
table: users,
where: "id = $${id}"
)
}
func main(): String {
let allSql = Generator.generate(allUsers())
let userSql = Generator.generate(userById("42"))
Terminal.println(allSql) // SELECT * FROM users;
Terminal.println(userSql) // SELECT * FROM users WHERE id = 42;
return "done"
}
Supported SQL Operations
SELECT — query rows from a table.
cmd [sql] search(term: String) {
SELECT(
table: products,
cols: "id, name, price",
where: "name LIKE '%$${term}%'",
order: "name ASC",
limit: "20"
)
}
INSERT — insert new rows.
cmd [sql] addProduct(name: String, price: String) {
INSERT(
table: products,
cols: "name, price",
values: "'$${name}', $${price}"
)
}
UPDATE — update existing rows.
cmd [sql] updatePrice(id: String, price: String) {
UPDATE(
table: products,
set: "price = $${price}",
where: "id = $${id}"
)
}
DELETE — remove rows.
cmd [sql] removeUser(id: String) {
DELETE(table: users, where: "id = $${id}")
}
CREATE-TABLE and CREATE-TABLE-IF — schema creation.
cmd [sql] createUsersTable() {
CREATE-TABLE-IF(
table: users,
cols: "id BIGSERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE"
)
}
DROP-TABLE, DROP-TABLE-IF, TRUNCATE, CREATE-INDEX, DROP-INDEX, ALTER-ADD, ALTER-DROP are also supported.
cmd [sql] addColumn(table: String, col: String) {
ALTER-ADD(table: $${table}, col: $${col})
}
cmd [sql] dropColumn(table: String, col: String) {
ALTER-DROP(table: $${table}, col: $${col})
}
Shell Commands
A bash generator can be registered and cmd templates used to model shell operations.
cmd [bash] buildProject(dir: String) {
run(cmd: "cd $${dir} && ./gradlew build")
}
Full Migration Example
Generate a complete schema migration file from model entities.
use TLang.Generator
use TLang.File
use TLang.Leaf
use TLang.StringBuilder
cmd [sql] createTable(tableName: String, cols: String) {
CREATE-TABLE-IF(
table: $${tableName},
cols: $${cols}
)
}
model {
set users { table: "users", cols: "id BIGSERIAL PRIMARY KEY, name TEXT, email TEXT UNIQUE" }
set products { table: "products", cols: "id BIGSERIAL PRIMARY KEY, name TEXT, price NUMERIC" }
set orders { table: "orders", cols: "id BIGSERIAL PRIMARY KEY, user_id BIGINT REFERENCES users(id), total NUMERIC" }
}
func main(): String {
let sb = StringBuilder.create()
let model = Leaf.model()
for (k in Leaf.keys(model)) {
let e = Leaf.get(model, k)
let sql = Generator.generate(createTable(e.table, e.cols))
let sb = StringBuilder.append(sb, sql)
}
let migration = StringBuilder.build(sb)
File.write("db/V1__init.sql", migration, true)
return "done"
}