3.3. Tools

Joedb comes with a collection of command-line tools.

3.3.1. joedbi

usage: joedbi <file> [<blob_file>]

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

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
 echo on|off
 prompt on|off

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

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>
 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>

Data manipulation
~~~~~~~~~~~~~~~~~
 insert_into <table_name> <record_id>
 insert_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>
 delete_from <table_name> <record_id>

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

3.3.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.3.3. joedb_logdump

usage: joedb_logdump [--sql] [--sqlite] [--raw] [--header] [--schema-only] [--ignore-errors] [--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:

-- 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";
-- End of automatic schema upgrade
INSERT INTO "city"("__id") VALUES(1);
UPDATE "city" SET "name" = X'546f6b796f' WHERE "__id" = 1;
INSERT INTO "city"("__id") VALUES(2);
UPDATE "city" SET "name" = X'4e657720596f726b' WHERE "__id" = 2;
INSERT INTO "city"("__id") VALUES(3);
UPDATE "city" SET "name" = X'5061726973' WHERE "__id" = 3;
INSERT INTO "city"("__id") VALUES(4);
UPDATE "city" SET "name" = X'4c696c6c65' WHERE "__id" = 4;
INSERT INTO "city"("__id") VALUES(5);
UPDATE "city" SET "name" = X'416d7374657264616d' WHERE "__id" = 5;
INSERT INTO "person"("__id") VALUES(1);
UPDATE "person" SET "first_name" = X'52c3a96d69' WHERE "__id" = 1;
UPDATE "person" SET "last_name" = X'436f756c6f6d' WHERE "__id" = 1;
UPDATE "person" SET "home" = 4 WHERE "__id" = 1;
INSERT INTO "person"("__id") VALUES(2);
UPDATE "person" SET "first_name" = X'4265727472616e64' WHERE "__id" = 2;
UPDATE "person" SET "last_name" = X'506963617264' WHERE "__id" = 2;
UPDATE "person" SET "home" = NULL WHERE "__id" = 2;
INSERT INTO "person"("__id") VALUES(3);
UPDATE "person" SET "first_name" = X'4172697374696465' WHERE "__id" = 3;
UPDATE "person" SET "last_name" = X'4d617274696e6573' WHERE "__id" = 3;
UPDATE "person" SET "home" = 5 WHERE "__id" = 3;
UPDATE "person" SET "last_name" = X'4d617274696e657a' WHERE "__id" = 3;
DELETE FROM "city" WHERE "__id" = 2;
-- 2024-05-02 12:23:10 GMT
-- The End

3.3.4. joedb_pack

usage: joedb_pack [--ignore-errors] [--checkpoint N] <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.3.5. joedb_convert

usage: joedb_convert [--ignore-errors] [--checkpoint N] <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. This happened in the early days of joedb, but is not likely to happen again in the future.

3.3.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.3.7. joedb_server

usage: joedb_server [--port p] [--timeout t] [--share] <file> <connection>

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

<connection> is one of:
 [dummy] (default) 
 dump 
 tail 
 file <file>
 network <host> <port>
 ssh <user> <host> <joedb_port> [<ssh_port> [<ssh_log_level>]]

The timeout is the time (in seconds) during which a client lock is kept.
0 (the default) means there is no timeout, and the lock is kept until the
client unlocks or is disconnected. A client that timed out is not disconnected,
and can still push data: the push will succeed only if there is no conflict.

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

3.3.8. joedb_multi_server

usage: joedb_multi_server <config.joedbi>

Run a server to share multiple databases. The config file contains joedbi commands to set server parameters. For instance:

insert_into server 1 "test_1.joedb" 2001 0
insert_into server 2 "test_2.joedb" 2002 0

The schema of the config file is this:

create_table server
add_field server file_name string
add_field server port int32
add_field server timeout int32

3.3.9. joedb_client

usage: joedb_client <file> <connection>

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

<connection> is one of:
 [dummy] (default) 
 dump 
 tail 
 file <file>
 network <host> <port>
 ssh <user> <host> <joedb_port> [<ssh_port> [<ssh_log_level>]]

3.3.10. joedb_push

usage: joedb_push [--follow] <file> <connection>

<file> is one of:
 [file] <file_name>
 sftp [--port p] [--verbosity v] <user> <host> <file_name>
 curl [--verbose] <URL>

<connection> is one of:
 [dump] (default) 
 tail 
 file <file>
 network <host> <port>
 ssh <user> <host> <joedb_port> [<ssh_port> [<ssh_log_level>]]

Pushes a local file to a connection. For example:

# Dump content of a file
joedb_push file.joedb dump
# 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 tail
# Keep a backup server updated
joedb_push --follow database.joedb network backup_server 1234

3.3.11. joedb_embed

usage: joedb_embed [--base64|raw|utf8|ascii] <file_name.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.3.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.3.13. joedb_browser

joedb_browser uses joedb_logdump to produce an SQLite database, and invokes sqlitebrowser to browse it.