Profiles / Programming
SD

SQL developer in MQL

Connections, DDL and DML with sql encode, transactions, cursors, parse, and exports to JSON, CSV, Excel and PDF on a real local database. Run the recipes in order: the first one creates the tuto_db_h2 database.

10 recipes on this page · open in the interactive view

Recipes
  1. Register a local H2 database connection
  2. Create a table and load rows safely
  3. Transactions: commit, rollback, all or nothing
  4. One value, one row, distinct values
  5. Query to JSON, then enrich the document
  6. Read a large result set by blocks
  7. Run MQL on each row with sql parse
  8. Export a query to CSV, Excel and PDF files
  9. CSV, XML and HTML for three partners
  10. sql encode or sql encode_std: the backslash trap
executed on MentDB

Register a local H2 database connection

Before writing any SQL, a developer declares the connection once in the connection manager: here an embedded H2 database in tmp/, built with the db.h2.embedded.config.get script. The recipe checks the registration and runs a first query, without ever printing the password.

Pipeline
Script
admin
#1. Build the H2 connection with the config script and register it;
cm set "tuto_db_h2" {execute "db.h2.embedded.config.get"
	"[database]" "./tmp/tuto_db_h2/shop"
	"[user]" "tuto"
	"[password]" "tuto_pwd"
;};
#2. Check it: registered, typed db, usable by SCRUD;
-> "[exists]" (cm exist "tuto_db_h2" "db");
-> "[as_file]" (cm exist "tuto_db_h2" "file");
-> "[scrud]" (string contains (cm show_scrud) "\"tuto_db_h2\"");
#3. Read the non secret fields only;
json load "tuto_db_cm" (cm get "tuto_db_h2");
-> "[info]" (concat (json select "tuto_db_cm" /subType) " " (json select "tuto_db_cm" /jdbc) ", properties: " (string regexp_replace (json fields "tuto_db_cm" /properties) "\s+" ""));
json unload "tuto_db_cm";
#The update script holds the password: count its lines, never print it;
-> "[gen_lines]" (string count (cm generate_update "tuto_db_h2") "json iobject");
#4. First query on the new database;
sql connect "tuto_db_s1" {cm get "tuto_db_h2";};
-> "[version]" (sql value "tuto_db_s1" "SELECT H2VERSION()");
-> "[sessions]" (sql show);
sql disconnect "tuto_db_s1";
concat "Registered as db: " [exists] ", as file: " [as_file] ", SCRUD ready: " [scrud] [_n_] [info] [_n_] "cm generate_update gives " [gen_lines] " field lines to edit" [_n_] "H2 version: " [version] ", open sessions: " (string regexp_replace [sessions] "\s+" "");
Result
mentdb
Registered as db: 1, as file: 0, SCRUD ready: 1
H2 jdbc:h2:./tmp/tuto_db_h2/shop, properties: ["DATABASE_TO_LOWER","password","MODE","user"]
cm generate_update gives 12 field lines to edit
H2 version: 2.1.214, open sessions: ["tuto_db_s1"]
Go further
executed on MentDB

Create a table and load rows safely

Create the orders table and load six orders that arrive as a JSON array. Every value goes through sql encode, so a customer called O'Brien cannot break the query or open an SQL injection.

Pipeline
Script
admin
#1. Open a session on the local H2 database;
sql connect "tuto_db_s1" {cm get "tuto_db_h2";};
#2. Recreate the table so that the recipe can be replayed;
sql dml "tuto_db_s1" "DROP TABLE IF EXISTS orders";
sql dml "tuto_db_s1" "CREATE TABLE orders (id INT PRIMARY KEY, customer VARCHAR(40) NOT NULL, product VARCHAR(40), qty INT, price DECIMAL(10,2), created DATE)";
#3. The rows to insert come as a JSON array;
json load "tuto_db_rows" "[
 {\"id\": 1, \"customer\": \"Dupont\", \"product\": \"Keyboard\", \"qty\": 2, \"price\": 49.90, \"created\": \"2026-10-02\"},
 {\"id\": 2, \"customer\": \"O'Brien\", \"product\": \"Monitor 27\", \"qty\": 1, \"price\": 289.00, \"created\": \"2026-10-05\"},
 {\"id\": 3, \"customer\": \"Dupont\", \"product\": \"Mouse\", \"qty\": 3, \"price\": 19.50, \"created\": \"2026-10-09\"},
 {\"id\": 4, \"customer\": \"Nakamura\", \"product\": \"Laptop\", \"qty\": 1, \"price\": 1249.00, \"created\": \"2026-10-12\"},
 {\"id\": 5, \"customer\": \"Silva\", \"product\": \"Mouse\", \"qty\": 5, \"price\": 19.50, \"created\": \"2026-10-20\"},
 {\"id\": 6, \"customer\": \"O'Brien\", \"product\": \"Keyboard\", \"qty\": 1, \"price\": 49.90, \"created\": \"2026-10-28\"}
]";
#4. One INSERT per row, every value goes through sql encode;
-> "[inserted]" 0;
json parse_array "tuto_db_rows" "/" "[row]" {
	json load "tuto_db_row" [row];
	-> "[inserted]" (+ [inserted] (sql dml "tuto_db_s1" (concat "INSERT INTO orders (id, customer, product, qty, price, created) VALUES ("
		(sql encode (json select "tuto_db_row" /id)) ", "
		(sql encode (json select "tuto_db_row" /customer)) ", "
		(sql encode (json select "tuto_db_row" /product)) ", "
		(sql encode (json select "tuto_db_row" /qty)) ", "
		(sql encode (json select "tuto_db_row" /price)) ", "
		(sql encode (json select "tuto_db_row" /created)) ")"
	)));
};
json unload "tuto_db_row";
json unload "tuto_db_rows";
#5. Check what the table now holds;
-> "[count]" (sql value "tuto_db_s1" "SELECT COUNT(*) FROM orders");
-> "[obrien]" (sql value "tuto_db_s1" (concat "SELECT COUNT(*) FROM orders WHERE customer=" (sql encode "O'Brien")));
sql disconnect "tuto_db_s1";
concat "Rows inserted: " [inserted] [_n_] "Rows in the table: " [count] [_n_] "Orders of O'Brien: " [obrien] [_n_] "The quote is escaped as: " (sql encode "O'Brien");
Result
mentdb
Rows inserted: 6
Rows in the table: 6
Orders of O'Brien: 2
The quote is escaped as: 'O''Brien'
Go further
  • Wrap the loop in a transaction with sql auto_commit false and sql commit to load thousands of rows faster.
  • Read the rows from a CSV file with csv parse instead of a JSON array.
executed on MentDB

Transactions: commit, rollback, all or nothing

With auto-commit off, a test order is inserted then cancelled with rollback; then a batch of two inserts fails on a duplicate key and is rolled back as a whole; finally a valid batch is committed.

Pipeline
Script
admin
#1. Open a session and switch to manual commit;
sql connect "tuto_db_s1" {cm get "tuto_db_h2";};
sql auto_commit "tuto_db_s1" false;
-> "[before]" (sql value "tuto_db_s1" "SELECT COUNT(*) FROM orders");
#2. A test order is inserted then cancelled with rollback;
sql dml "tuto_db_s1" (concat "INSERT INTO orders (id, customer, product, qty, price, created) VALUES (100, " (sql encode "Test") ", 'Cable', 1, 9.90, CURRENT_DATE)");
-> "[inside]" (sql value "tuto_db_s1" "SELECT COUNT(*) FROM orders");
sql rollback "tuto_db_s1";
-> "[after_rollback]" (sql value "tuto_db_s1" "SELECT COUNT(*) FROM orders");
#3. All or nothing: the second INSERT reuses id 1, so both are rolled back;
try {
	sql dml "tuto_db_s1" "INSERT INTO orders (id, customer, product, qty, price, created) VALUES (7, 'Silva', 'Webcam', 1, 59.00, '2026-10-30')";
	sql dml "tuto_db_s1" "INSERT INTO orders (id, customer, product, qty, price, created) VALUES (1, 'Silva', 'Headset', 1, 79.00, '2026-10-30')";
	sql commit "tuto_db_s1";
	-> "[batch]" "committed";
} {
	sql rollback "tuto_db_s1";
	-> "[batch]" (concat "rolled back, cause: " (string regexp_extract [err] "([A-Z][a-z ]+violation)" 1) ", SQLSTATE " (string regexp_extract [err] "\[(\d{5})-" 1));
} "[err]";
#4. A valid batch is committed;
sql dml "tuto_db_s1" "INSERT INTO orders (id, customer, product, qty, price, created) VALUES (7, 'Silva', 'Webcam', 1, 59.00, '2026-10-30')";
sql commit "tuto_db_s1";
-> "[final]" (sql value "tuto_db_s1" "SELECT COUNT(*) FROM orders");
sql auto_commit "tuto_db_s1" true;
sql disconnect "tuto_db_s1";
concat "Before: " [before] " | inside the transaction: " [inside] " | after rollback: " [after_rollback] [_n_] "Batch with a duplicate key: " [batch] [_n_] "After the valid commit: " [final];
Result
mentdb
Before: 6 | inside the transaction: 7 | after rollback: 6
Batch with a duplicate key: rolled back, cause: Unique index or primary key violation, SQLSTATE 23505
After the valid commit: 7
Go further
  • Read the SQLSTATE code of an error with string regexp_extract to decide whether to retry.
  • Put the batch in a script and run it through the stack with stack to retry it automatically.
executed on MentDB

One value, one row, distinct values

The three quick reads of every API: a single value (October turnover), a single row (the biggest order) and the distinct values of a column (customers who bought a mouse).

Pipeline
Script
admin
#1. Open a session;
sql connect "tuto_db_s1" {cm get "tuto_db_h2";};
#2. One value: the turnover of October;
-> "[turnover]" (sql value "tuto_db_s1" "SELECT SUM(qty * price) FROM orders WHERE created BETWEEN '2026-10-01' AND '2026-10-31'");
#3. One row: the biggest order;
-> "[top]" (sql row "tuto_db_s1" "SELECT id, customer, product, qty * price AS amount FROM orders ORDER BY qty * price DESC LIMIT 1");
#4. The distinct values of a column: who bought a mouse;
-> "[buyers]" (sql col_distinct "tuto_db_s1" (concat "SELECT customer FROM orders WHERE product=" (sql encode "Mouse")));
sql disconnect "tuto_db_s1";
#5. Read one field of the row;
json load "tuto_db_top" [top];
-> "[top_customer]" (json select "tuto_db_top" /customer);
json unload "tuto_db_top";
#6. col_distinct returns an object whose fields are the distinct values;
json load "tuto_db_buyers" [buyers];
-> "[buyer_list]" (string regexp_replace (json fields "tuto_db_buyers" /) "\s+" "");
json unload "tuto_db_buyers";
concat "Turnover October: " [turnover] [_n_] "Biggest order: " (string regexp_replace [top] "\s+" " ") [_n_] "Customer of the biggest order: " [top_customer] [_n_] "Mouse buyers: " [buyer_list];
Result
mentdb
Turnover October: 1902.70
Biggest order: { "product": "Laptop", "amount": "1249.00", "id": "4", "customer": "Nakamura" }
Customer of the biggest order: Nakamura
Mouse buyers: ["Silva","Dupont"]
Go further
  • Pass user input to the WHERE clause only through sql encode.
  • Return the row directly from a get script to build a detail endpoint.
executed on MentDB

Query to JSON, then enrich the document

The orders of a customer are read as a JSON document, then each line gets a computed amount field and the document gets the customer name: the typical body of a REST answer.

Pipeline
Script
admin
#1. Open a session and get the orders of a customer as JSON;
sql connect "tuto_db_s1" {cm get "tuto_db_h2";};
json load "tuto_db_res" (sql to json "tuto_db_s1" "orders" (concat "SELECT id, product, qty, price FROM orders WHERE customer=" (sql encode "Dupont") " ORDER BY id"));
sql disconnect "tuto_db_s1";
#2. Navigate in the result;
-> "[nb]" (json count "tuto_db_res" /data);
-> "[cols]" (json select "tuto_db_res" /columns);
-> "[first]" (json select "tuto_db_res" /data[0]/product);
#3. Add a computed field to each line;
for (-> "[i]" 0) (< [i] [nb]) (++ "[i]") {
	-> "[amount]" (bd* (json select "tuto_db_res" (concat "/data[" [i] "]/qty")) (json select "tuto_db_res" (concat "/data[" [i] "]/price")));
	json iobject "tuto_db_res" (concat "/data[" [i] "]") "amount" [amount] NUM;
};
json iobject "tuto_db_res" / "customer" "Dupont" STR;
-> "[out]" (json doc "tuto_db_res");
json unload "tuto_db_res";
[out];
Result
mentdb
{
  "data": [
    {
      "product": "Keyboard",
      "amount": 99.8,
      "price": "49.90",
      "qty": "2",
      "id": "1"
    },
    {
      "product": "Mouse",
      "amount": 58.5,
      "price": "19.50",
      "qty": "3",
      "id": "3"
    }
  ],
  "columns": [
    "id",
    "product",
    "qty",
    "price"
  ],
  "table": "orders",
  "customer": "Dupont"
}
Go further
  • Sort the lines with json sort before returning them.
  • Use sql to xml for a partner that expects XML.
executed on MentDB

Read a large result set by blocks

A cursor is opened on the table and read three rows at a time, as a batch would do on millions of rows without loading everything in memory. Each block is summed and logged.

Pipeline
Script
admin
#1. Open a cursor on the whole table;
sql connect "tuto_db_s1" {cm get "tuto_db_h2";};
sql block open "tuto_db_s1" "orders" "SELECT id, customer, qty, price FROM orders ORDER BY id";
#2. Read it 3 lines at a time, as a batch job would do with millions of rows;
-> "[page]" 0;
-> "[total]" 0;
-> "[log]" "";
-> "[nb]" 1;
while (> [nb] 0) {
	json load "tuto_db_blk" (sql block to_json 3);
	-> "[nb]" (json count "tuto_db_blk" /data);
	if (> [nb] 0) {
		++ "[page]";
		-> "[ids]" "";
		for (-> "[i]" 0) (< [i] [nb]) (++ "[i]") {
			-> "[ids]" (concat [ids] (json select "tuto_db_blk" (concat "/data[" [i] "]/id")) " ");
			-> "[total]" (bd+ [total] (bd* (json select "tuto_db_blk" (concat "/data[" [i] "]/qty")) (json select "tuto_db_blk" (concat "/data[" [i] "]/price"))));
		};
		-> "[log]" (concat [log] "Block " [page] ": " [nb] " rows, ids " [ids] [_n_]);
	};
};
#3. Close the cursor and the session;
sql block close;
json unload "tuto_db_blk";
sql disconnect "tuto_db_s1";
concat [log] "Total amount: " [total];
Result
mentdb
Block 1: 3 rows, ids 1 2 3
Block 2: 3 rows, ids 4 5 6
Block 3: 1 rows, ids 7
Total amount: 1902.70
Go further
  • Write each block to a file with file append to export a huge table.
  • Commit every block in a target database to copy a table.
executed on MentDB

Run MQL on each row with sql parse

sql parse calls an MQL block for every row, with each column in a T_ variable. The recipe flags the orders above 200 and accumulates the amount per customer in a JSON report.

Pipeline
Script
admin
#1. Run an MQL action on each row, each column arrives as a T_ variable;
sql connect "tuto_db_s1" {cm get "tuto_db_h2";};
json load "tuto_db_report" "{\"big\": [], \"by_customer\": {}}";
-> "[nb]" 0;
sql parse "tuto_db_s1" "T" (concat "SELECT customer, product, qty, price FROM orders ORDER BY id") {
	++ "[nb]";
	-> "[amount]" (bd* [T_qty] [T_price]);
	#2. Flag the orders above 200;
	if (> [amount] 200) {
		json iarray "tuto_db_report" /big (concat [T_customer] ": " [T_product] " for " [amount]) STR;
	};
	#3. Accumulate the amount per customer;
	-> "[prev]" (json select "tuto_db_report" (concat "/by_customer/" [T_customer]));
	if (is null [prev]) {-> "[prev]" 0;};
	json uobject "tuto_db_report" /by_customer [T_customer] (bd+ [prev] [amount]) NUM;
};
sql disconnect "tuto_db_s1";
json iobject "tuto_db_report" / "rows" [nb] INT;
-> "[out]" (json doc "tuto_db_report");
json unload "tuto_db_report";
[out];
Result
mentdb
{
  "big": [
    "O\u0027Brien: Monitor 27 for 289.00",
    "Nakamura: Laptop for 1249.00"
  ],
  "rows": 7,
  "by_customer": {
    "Silva": 156.5,
    "Dupont": 158.3,
    "Nakamura": 1249.0,
    "O\u0027Brien": 338.9
  }
}
Go further
  • Call another script per row with execute to keep the action reusable.
  • Compare with sql block to_json when the action needs several rows at once.
executed on MentDB

Export a query to CSV, Excel and PDF files

The same query is exported to CSV, XLS, XLSX and PDF in a work folder, then each file is read back to check it: CSV lines, Excel sheet and last cell, PDF pages and text. The folder is deleted at the end.

Pipeline
Script
admin
#1. Prepare the output folder and a query timeout;
-> "[dir]" "tmp/tuto_db_export";
file mkdir [dir];
sql set_timeout 30;
sql connect "tuto_db_s1" {cm get "tuto_db_h2";};
-> "[q]" "SELECT id, customer, product, qty, price, qty * price AS amount FROM orders ORDER BY id";
#2. The same query in four file formats;
sql to csv_file "tuto_db_s1" (concat [dir] "/orders.csv") [q] ";" "\"";
sql to excel "tuto_db_s1" "orders" [q] (concat [dir] "/orders.xls");
sql to excelx "tuto_db_s1" "orders" [q] (concat [dir] "/orders.xlsx");
sql to pdf "tuto_db_s1" "orders" [q] (concat [dir] "/orders.pdf");
sql disconnect "tuto_db_s1";
#3. Read the files back to check them;
-> "[csv_lines]" (file count_lines (concat [dir] "/orders.csv"));
excelx load "tuto_db_xl" (concat [dir] "/orders.xlsx");
-> "[sheets]" (excelx sheet show "tuto_db_xl");
-> "[sheet]" (json load select "tuto_db_sh" [sheets] /[0]);
-> "[last_row]" (excelx sheet max_row "tuto_db_xl" [sheet]);
-> "[cell]" (excelx cell get "tuto_db_xl" [sheet] [last_row] 1);
excelx close "tuto_db_xl";
json unload "tuto_db_sh";
-> "[pages]" (pdf page_count_file (concat [dir] "/orders.pdf"));
-> "[pdf_has_laptop]" (string contains (pdf extract_text (concat [dir] "/orders.pdf")) "Laptop");
-> "[xls_ok]" (file exist (concat [dir] "/orders.xls"));
#4. Clean up;
file delete [dir];
concat "CSV lines: " [csv_lines] [_n_] "Excel sheet: " [sheet] ", last row " [last_row] ", customer of that row: " [cell] [_n_] "PDF pages: " [pages] ", contains Laptop: " [pdf_has_laptop] [_n_] "XLS created: " [xls_ok] [_n_] "Folder still there: " (file exist [dir]);
Result
mentdb
CSV lines: 8
Excel sheet: orders, last row 7, customer of that row: Silva
PDF pages: 1, contains Laptop: 1
XLS created: 1
Folder still there: 0
Go further
  • Send the files with mail send or drop them on an SFTP server.
  • Generate a styled PDF from your own HTML with pdf from html.
executed on MentDB

CSV, XML and HTML for three partners

One query feeds three partners: accounting gets a CSV file (re-read with csv parse to check the total), the ERP gets XML, the sales manager gets the HTML table converted into a PDF.

Pipeline
Script
admin
#1. One query, three text formats for three partners;
sql connect "tuto_db_s1" {cm get "tuto_db_h2";};
-> "[q]" "SELECT id, customer, qty, price FROM orders WHERE created >= '2026-10-10' ORDER BY id";
-> "[csv]" (sql to csv "tuto_db_s1" "orders" [q] ";" "\"");
-> "[xml]" (sql to xml "tuto_db_s1" "orders" [q]);
-> "[html]" (sql to html "tuto_db_s1" "orders" [q]);
sql disconnect "tuto_db_s1";
#2. Accounting gets the CSV file, re-read here line by line with csv parse;
file mkdir "tmp/tuto_db_share";
file create "tmp/tuto_db_share/orders.csv" [csv] "UTF-8";
-> "[check]" 0;
csv parse (mql "R") (mql "tmp/tuto_db_share/orders.csv") (mql ";") (mql "\"") (mql "") {
	-> "[check]" (bd+ [check] (bd* [R_qty] [R_price]));
};
#3. The HTML table becomes a PDF for the sales manager;
pdf from html [html] "tmp/tuto_db_share/orders.pdf";
-> "[pages]" (pdf page_count_file "tmp/tuto_db_share/orders.pdf");
file delete "tmp/tuto_db_share";
#4. The XML goes to the ERP: count its items;
concat "CSV header: " (atom get [csv] 1 [_n_]) [_n_] "Amount re-read from the CSV file: " [check] [_n_] "XML rows for the ERP: " (string count [xml] "<customer>") [_n_] "PDF pages: " [pages];
Result
mentdb
CSV header: id;customer;qty;price
Amount re-read from the CSV file: 1455.40
XML rows for the ERP: 4
PDF pages: 1
Go further
  • Write the CSV straight to disk with sql to csv_file.
  • Parse the XML with the XML family before sending it.
executed on MentDB

sql encode or sql encode_std: the backslash trap

A Windows path with a quote is stored in H2 twice. sql encode also doubles backslashes, which is right for MySQL only; sql encode_std doubles only the quotes, which is right for H2, PostgreSQL, Oracle or SQL Server.

Pipeline
Script
admin
#1. A value with a quote and backslashes, as typed by a user;
-> "[path]" "C:\exports\l'ete.csv";
-> "[mysql_style]" (sql encode [path]);
-> "[std_style]" (sql encode_std [path]);
#2. Store it twice in a work table of the H2 database;
sql connect "tuto_db_s1" {cm get "tuto_db_h2";};
sql dml "tuto_db_s1" "CREATE TABLE IF NOT EXISTS tuto_notes (id INT PRIMARY KEY, txt VARCHAR(100))";
sql dml "tuto_db_s1" "DELETE FROM tuto_notes";
sql dml "tuto_db_s1" (concat "INSERT INTO tuto_notes VALUES (1, " [mysql_style] ")");
sql dml "tuto_db_s1" (concat "INSERT INTO tuto_notes VALUES (2, " [std_style] ")");
#3. Read back and compare with the original;
-> "[back1]" (sql value "tuto_db_s1" "SELECT txt FROM tuto_notes WHERE id=1");
-> "[back2]" (sql value "tuto_db_s1" "SELECT txt FROM tuto_notes WHERE id=2");
-> "[null_sql]" (sql encode null);
sql dml "tuto_db_s1" "DROP TABLE tuto_notes";
sql disconnect "tuto_db_s1";
concat "sql encode     : " [mysql_style] " -> stored " [back1] " -> same: " (equal [back1] [path]) [_n_] "sql encode_std : " [std_style] " -> stored " [back2] " -> same: " (equal [back2] [path]) [_n_] "A null value becomes: " [null_sql];
Result
mentdb
sql encode     : 'C:\\exports\\l''ete.csv' -> stored C:\\exports\\l'ete.csv -> same: 0
sql encode_std : 'C:\exports\l''ete.csv' -> stored C:\exports\l'ete.csv -> same: 1
A null value becomes: null
Go further
  • Choose the encode function from the connection subType read with cm get.
  • Null values become the SQL keyword null with both functions.

Also in Programming

MB
MQL beginner
Variables, operators, if, loops and your first try/exception: learn MQL step by step.
10 recipes
MD
MQL developer
Atom lists, data types, constants, translations, session variables and error patterns.
10 recipes
BW
Backend & web service developer
Typed scripts, execute / call / include, generated calls and URLs, parameters and logs.
10 recipes
DT
Date & time developer
Calendars, business days, time zones, ISO and epoch, durations, quarters and week numbers.
10 recipes
SE
String & encoding developer
Cleaning, case styles, regex, URL/HTML/Base64 encodings, number bases and encryption.
10 recipes
DV
Data validation developer
IBAN, BIC, SIRET, Luhn, email, IP, UUID, JSON and date checks gathered in a validation report.
10 recipes
JD
JSON & document store developer
In-memory JSON documents, persistent nodes and sequences: build, walk, sort, clean up.
10 recipes
SD
Script developer
Full script lifecycle in the MQL editor: typed parameters, read back, generate, patch, deploy, copy, grant, delete.
10 recipes
EM
Execution modes
execute, call, include, sub_include, parallel, stack: which environment, which checks, which logs.
11 recipes
WS
Web service developer
A small REST resource with get, post, put and delete scripts: validation, JSON answers, codes, grants, URLs and API docs.
10 recipes
AD
Async developer
Asynchronous processing with the stack: push runs now or later, priorities and parallel limits, errors and replays, flows and cleanup.
10 recipes
SD
Scheduler developer
Cron jobs and delayed runs: add, resume, pause, update and remove jobs, prove they ran, and postpone stack runs with a delay condition.
10 recipes
ED
Event developer
Event-driven scripts: file watchers that push each file event to the stack, validation, archiving, errors and safe restarts.
10 recipes
CC
Configuration & connections
Parameters (private, described, locked, deployed), environment variables, sessions and connections used by your scripts.
12 recipes
VD
Versioning & deployment
Group your scripts, commit, compare, roll back, export, import and package a release.
10 recipes
DE
Debugging & error handling
Coded errors with try/exception, logs with correlation ids, timing, metrics and defensive checks.
10 recipes
CD
CRUD & data API developer
Generate SCRUD scripts from a table, patch and install them, write typed read and write APIs, check data quality and manage connections per environment. Uses the tuto_db_h2 database of the SQL developer recipes; the last recipe removes it.
10 recipes
WA
Web application developer
Create a web app, its host name, pages, ajax forms, menu and grants, then remove it all.
10 recipes
AI
Algorithms in MQL
Sorting, searching, recursion, data structures and number algorithms: MQL is a real programming language.
10 recipes
CF
Control flow
if, if force, case, switch, mode, for, while, repeat, break, continue, parallel and synchronized on real cases.
10 recipes
TM
The MQL language in depth
Data types and null, booleans, comments, variables and scope, eval and mql blocks, coded errors and try.
10 recipes
SU
Screen & UI developer (sajax)
Build the screens of MentDB web apps in MQL: Bootstrap grids, forms and every control, ajax buttons, alerts, refreshes and charts.
10 recipes