3.4. Tools

Joedb comes with a collection of command-line tools.

3.4.1. joedbi

usage: joedbi [--max_record_id <n>] <file>

<file> is one of:
 [file] [--<open_mode>] <file_name>
 <open_mode> is one of:
  read
  write
  new
  write_or_new*
  lock
 memory
 interpreted [--read] <file_name>
 sftp [--port p] [--verbosity v] <user> <host> <file_name>
 curl [--verbose] <URL>
 brotli [--read] <file_name>

joedbi is the joedb interpreter. It has commands to let you directly modify a file, and visualize the content of tables.

Below is a list of commands the interpreter understands:


General commands
~~~~~~~~~~~~~~~~
 about
 help|?
 quit
 abort
 echo on|off
 prompt on|off

Journal
~~~~~~~
 timestamp [<stamp>] (if no value is given, use current time)
 comment "<comment_string>"
 valid_data
 flush
 [soft_]checkpoint
 hard_checkpoint
 write_blob <data_string>

Displaying data
~~~~~~~~~~~~~~~
 table <table_name> [<max_column_width>] [start] [length]
 record <table_name> [<record_id>]
 schema
 dump
 sql
 json [<base64>]

Data manipulation
~~~~~~~~~~~~~~~~~
 insert_into <table_name> <record_id>
 delete_from <table_name> <record_id>
 insert_vector <table_name> <record_id> <size>
 delete_vector <table_name> <record_id> <size>
 update <table_name> <record_id> <field_name> <value>
 update_vector <table_name> <record_id> <field_name> <N> <v_1> ... <v_N>

Data definition
~~~~~~~~~~~~~~~
 create_table <table_name>
 drop_table <table_name>
 rename_table <old_table_name> <new_table_name>
 add_field <table_name> <field_name> <type> [default <value>]
 drop_field <table_name> <field_name>
 rename_field <table_name> <old_field_name> <new_field_name>
 custom <custom_name>

 <type> may be:
  string,
  blob,
  int8, int16, int32, int64,
  float32, float64,
  boolean,
  references <table_name>

Blob Reader
~~~~~~~~~~~
 read_blob <blob> [<output_file_name>]

3.4.2. joedbc

usage: joedbc file.joedbi file.joedbc

joedbc is the joedb compiler. It takes two file names as parameters. The first file should contain joedbi commands to create the database schema. The second file contains compiler options.

The joedbc file must at least contain a namespace option that indicates the namespace in which the code will be generated. It can also be used to define indexes.

3.4.3. joedb_logdump

usage: joedb_logdump [--sql] [--raw] [--header] [--schema_only] [--ignore_header] [--load] [--print_checkpoint] [--blob] file.joedb

joedb_logdump takes a joedb file name as parameter, and produces a sequence of joedbi commands. With the --sql option, it can produce SQL output. This way, joedb data can be easily imported into any system that understands SQL.

For instance, this is the SQL output of the tutorial database:

BEGIN TRANSACTION; -- checkpoint = 41
-- Automatic schema upgrade
CREATE TABLE "city"("__id" INTEGER PRIMARY KEY);
ALTER TABLE "city" ADD "name" TEXT;
CREATE TABLE "person"("__id" INTEGER PRIMARY KEY);
ALTER TABLE "person" ADD "first_name" TEXT;
ALTER TABLE "person" ADD "last_name" TEXT;
ALTER TABLE "person" ADD "home" INTEGER REFERENCES "city";
-- valid data
INSERT INTO "city"("__id") VALUES(0);
UPDATE "city" SET "name" = X'546f6b796f' WHERE "__id" = 0;
INSERT INTO "city"("__id") VALUES(1);
UPDATE "city" SET "name" = X'4e657720596f726b' WHERE "__id" = 1;
INSERT INTO "city"("__id") VALUES(2);
UPDATE "city" SET "name" = X'5061726973' WHERE "__id" = 2;
INSERT INTO "city"("__id") VALUES(3);
UPDATE "city" SET "name" = X'4c696c6c65' WHERE "__id" = 3;
INSERT INTO "city"("__id") VALUES(4);
UPDATE "city" SET "name" = X'416d7374657264616d' WHERE "__id" = 4;
INSERT INTO "person"("__id") VALUES(0);
UPDATE "person" SET "first_name" = X'52c3a96d69' WHERE "__id" = 0;
UPDATE "person" SET "last_name" = X'436f756c6f6d' WHERE "__id" = 0;
UPDATE "person" SET "home" = 3 WHERE "__id" = 0;
INSERT INTO "person"("__id") VALUES(1);
UPDATE "person" SET "first_name" = X'4265727472616e64' WHERE "__id" = 1;
UPDATE "person" SET "last_name" = X'506963617264' WHERE "__id" = 1;
UPDATE "person" SET "home" = NULL WHERE "__id" = 1;
INSERT INTO "person"("__id") VALUES(2);
UPDATE "person" SET "first_name" = X'4172697374696465' WHERE "__id" = 2;
UPDATE "person" SET "last_name" = X'4d617274696e6573' WHERE "__id" = 2;
UPDATE "person" SET "home" = 4 WHERE "__id" = 2;
UPDATE "person" SET "last_name" = X'4d617274696e657a' WHERE "__id" = 2;
DELETE FROM "city" WHERE "__id" = 1;
-- 2025-06-13 13:28:01 GMT
-- The End
COMMIT; --checkpoint = 285

3.4.4. joedb_pack

usage: joedb_pack [--ignore_header] [--until <checkpoint>] input.joedb output.joedb

Packing a file removes all its history, and keeps only the most recent data.

In order to support schema recognition (see Schema Upgrade), data-definition commands are not packed. They are left as-is, at the beginning of the log, in the same order as in the original file.

3.4.5. joedb_convert

usage: joedb_convert [--ignore_header] [--until <checkpoint>] input.joedb output.joedb

This copies the input to the output. --ignore-error sets the checkpoint value to the file length, and can be used to recover a damaged file.

In case the joedb file format ever changes in a way that is not compatible with the previous version, then this tool can be used to perform the conversion. The new format is first implemented in write functions. At this moment, joedb_convert is still able to read the old format, and writes the new format.

3.4.6. joedb_merge

usage: joedb_merge <db_1.joedb> ... <db_N.joedb> <output.joedb>
or read file names from input stream: joedb_merge <output.joedb> <file_list.txt
Note: output file must not already exist

joedb_merge merges multiple files with the same schema into a single file that contains the concatenation of all tables. References are translated. Duplicates are not eliminated.

For instance, when merging those two databases:

{
 "city":
 {
  "__size": 2,
  "name": ["Lille", "Paris"]
 },
 "person":
 {
  "__size": 2,
  "first_name": ["Rémi", "Bill"],
  "last_name": ["Coulom", "Jordan"],
  "home": [0, 1]
 }
}
{
 "city":
 {
  "__size": 2,
  "name": ["Lille", "Barcelona"]
 },
 "person":
 {
  "__size": 2,
  "first_name": ["Albert", "Aristide"],
  "last_name": ["Dupont", "Martinez"],
  "home": [0, 1]
 }
}

joedb_merge produces this result:

{
 "city":
 {
  "__size": 4,
  "name": ["Lille", "Paris", "Lille", "Barcelona"]
 },
 "person":
 {
  "__size": 4,
  "first_name": ["Rémi", "Bill", "Albert", "Aristide"],
  "last_name": ["Coulom", "Jordan", "Dupont", "Martinez"],
  "home": [0, 1, 2, 3]
 }
}

3.4.7. joedb_server

usage: joedb_server [--socket <endpoint_path>] [--timeout <seconds>] [--hard_checkpoint] [--check none|fast*|full] [--recovery none*|ignore_header|overwrite] [--db none*|interpreted|dump|dump_tail|sql|sql_tail] <file> <connection>

<file> is one of:
 [file] [--<open_mode>] <file_name>
 <open_mode> is one of:
  read
  write
  new
  write_or_new*
  shared
  lock
 memory
 interpreted [--read] <file_name>
 sftp [--port p] [--verbosity v] <user> <host> <file_name>
 curl [--verbose] <URL>
 brotli [--read] <file_name>
 server (client must use a connection to a server)

<connection> is one of:
 [dummy] (default) 
 file <file>
 local <endpoint_path>
 ssh <user> <host> <endpoint_path> [<ssh_port> [<ssh_log_level>]]

Run a server to share a single database. See Concurrency for more information.

3.4.8. joedb_multi_server

usage: joedb_multi_server [--timeout <seconds>] <file.joedb>+

3.4.9. joedb_client

usage: joedb_client [--hard_checkpoint] [--check none|fast*|full] [--recovery none*|ignore_header|overwrite] [--db none|interpreted*|dump|dump_tail|sql|sql_tail] <file> <connection>

<file> is one of:
 [file] [--<open_mode>] <file_name>
 <open_mode> is one of:
  read
  write
  new
  write_or_new
  shared*
  lock
 memory
 interpreted [--read] <file_name>
 sftp [--port p] [--verbosity v] <user> <host> <file_name>
 curl [--verbose] <URL>
 brotli [--read] <file_name>
 server (client must use a connection to a server)

<connection> is one of:
 [dummy] (default) 
 file <file>
 local <endpoint_path>
 ssh <user> <host> <endpoint_path> [<ssh_port> [<ssh_log_level>]]

3.4.10. joedb_push

usage: joedb_push [--follow] [--until <checkpoint>] [--hard_checkpoint] [--check none|fast*|full] [--recovery none*|ignore_header|overwrite] [--db none*|interpreted|dump|dump_tail|sql|sql_tail] <file> <connection>

<file> is one of:
 [file] <file_name>
 interpreted [--read] <file_name>
 sftp [--port p] [--verbosity v] <user> <host> <file_name>
 curl [--verbose] <URL>
 brotli <file_name>
 server (client must use a connection to a server)

<connection> is one of:
 [dummy] (default) 
 file <file>
 local <endpoint_path>
 ssh <user> <host> <endpoint_path> [<ssh_port> [<ssh_log_level>]]

Pushes a local file to a connection. For example:

# Dump content of a file
joedb_push file.joedb --db dump 2>/dev/null
# Truncate a file containing an aborted transaction
joedb_push broken.joedb file fixed.joedb
# Follow additions to the end of a file
joedb_push --follow file.joedb --db dump_tail
# Keep a backup server updated
joedb_push --follow database.joedb ssh user host ~/backup.joedb.sock
# Export a joedb file to sqlite
joedb_push database.joedb --db sql | sqlite3 database.sqlite
# Compress a database
joedb_push database.joedb file brotli compressed.joedb

3.4.11. joedb_embed

usage: joedb_embed [--mode base64|raw|utf8|ascii*] <file.joedb> <namespace> <identifier>
output: <namespace>_<identifer>.{h,cpp}

joedb_embed compiles a joedb database file into a C++ string literal, and a function to open it as a Database.

3.4.12. joedb_to_json

joedb_to_json takes a joedb file name as parameter, and produces json output. Each column is represented as a vector, and references are indexes into the vector (-1 indicates the null reference). The --base64 option encodes strings in base64. Joedb considers a string as a vector of bytes that may take any value, but json strings are limited to UTF-8. So --base64 might be necessary for binary data or other special characters.

This is the json output of the tutorial database:

{
 "city":
 {
  "__size": 4,
  "name": ["Tokyo", "Paris", "Lille", "Amsterdam"]
 },
 "person":
 {
  "__size": 3,
  "first_name": ["Rémi", "Bertrand", "Aristide"],
  "last_name": ["Coulom", "Picard", "Martinez"],
  "home": [2, -1, 3]
 }
}

3.4.13. joedb_edit

joedb_edit is a bash script that dumps a joedb file to a temporary text file and opens the default text editor to modify it. Modifications will be pushed to the original if possible. Otherwise the user is given the option to overwrite the original file.

3.4.14. joedb_browser

joedb_browser is a bash script that produces an SQLite database, and invokes sqlitebrowser to browse it.