Skip to content
immudb docker run -d --net host -it --name immudb codenotary/immudb:latest

CLI Tools

Before any operations can be run by immuadmin or immuclient, it is necessary to authenticate against the running immudb server.

When immudb is first run, it is ready to use immediately with the default database and credentials:

  • Database name: defaultdb
  • User: immudb
  • Password: immudb
  • Address: 127.0.0.1
  • Port: 3322

immuadmin#

immuadmin is the admin client for immudb. It is used for a variety of tasks such as creating and updating databases and users. Creating backups, restoring from backups etc.

You may download the immuadmin binary from the latest releases on Github . Once you have downloaded immuadmin, rename it to immuadmin, make sure to mark it as executable, then run it. The following example shows how to obtain v1.3.0 for Linux amd64:

1$ wget https://github.com/vchain-us/immudb/releases/download/v1.3.0/immuadmin-v1.3.0-linux-amd64
2$ mv immuadmin-v1.3.0-linux-amd64 immuadmin
3$ chmod +x immuadmin

Alternatively, you may pull immuadmin docker image from DockerHub and run it in a ready-to-use container:

1$ docker run -it --rm --name immuadmin codenotary/immuadmin:latest status

Basic operations#

To get started we need to login to immuadmin first. The admin user is the similar to the root user in MySQL etc.

1$ ./immuadmin login immudb
2Password: immudb

Once logged in we can create a new database using

1$ ./immuadmin database create mydatabase
2database 'mydatabase' {replica: false} successfully created

To switch to our newly created database

1$ ./immuclient use mydatabase
2Now using mydatabase

To create new user with read/write access to just created database

1$ ./immuadmin user create user1 readwrite mydatabase
2Choose a password for user1:
3Confirm password:

For detailed description of immuadmin command arguments use help

1$ ./immuadmin help

immuclient#

immuclient is used for interacting with databases, like reading, writing and querying for data or invoking SQL.

You may download the immuclient binary from the latest releases on Github . Once you have downloaded immuclient, rename it to immuclient, make sure to mark it as executable, then run it. The following example shows how to obtain v1.3.0 for Linux amd64:

1$ wget https://github.com/vchain-us/immudb/releases/download/v1.3.0/immuclient-v1.3.0-linux-amd64
2$ mv immuclient-v1.3.0-linux-amd64 immuclient
3$ chmod +x immuclient

Alternatively, you may pull immuclient docker image from DockerHub and run it in a ready-to-use container:

1$ docker run -it --rm --net host --name immuclient codenotary/immuclient:latest

Basic operations#

To display all available options and their description run:

1$ ./immuclient help

Running login immudb from within immuclient will use the default database name and port. All you need to supply is the user and password:

1$ ./immuclient login immudb
2Password: immudb

While immudb supports set and get for key-value storing and retrieving, its immutability means that we can verify the integrity of the underlying Merkle tree. To do this, we use the safeset and safeget commands. Let’s try setting a value of 100 for the key balance:

1$ ./immuclient safeset balance 100
2tx:             2
3key:            balance
4value:          100
5verified:       true

Then, we can immediately overwrite the key balance with a value of 9001 instead:

1$ ./immuclient safeset balance 9001
2tx:             3
3key:            balance
4value:          9001
5verified:       true

If we try to retrieve the current value of key balance, we should get 9001:

1$ ./immuclient safeget balance
2tx:             3
3key:            balance
4value:          9001
5verified:       true 

Note that at each step so far, the verified flag is set to true. This ensures that the Merkle tree remains consistent for each transaction.

We can show the history of transactions for key balance using the history command:

1$ ./immuclient history balance
2tx:             2
3key:            balance
4value:          100
5
6tx:             3
7key:            balance
8value:          9001

SQL operations#

In addition to a key-value store, immudb supports the relational model (SQL). For example, to create a table:

1$ ./immuclient exec "CREATE TABLE people(id INTEGER, name VARCHAR, salary INTEGER, PRIMARY KEY id);"
2Updated rows: 0

To insert data, use UPSERT (insert or update), which will add an entry, or overwrite it if already exists (based on the primary key):

1$ ./immuclient exec "UPSERT INTO people(id, name, salary) VALUES (1, 'Joe', 10000);"
2Updated rows: 1
3$ ./immuclient exec "UPSERT INTO people(id, name, salary) VALUES (2, 'Bob', 30000);"
4Updated rows: 1

To query the data you can use the traditional SELECT:

1$ ./immuclient query "SELECT id, name, salary FROM people;"
2+------------------------+--------------------------+----------------------------+
3| (MYDATABASE PEOPLE ID) | (MYDATABASE PEOPLE NAME) | (MYDATABASE PEOPLE SALARY) |
4+------------------------+--------------------------+----------------------------+
5|                      1 | "Joe"                    |                      10000 |
6|                      2 | "Bob"                    |                      30000 |
7+------------------------+--------------------------+----------------------------+

If we upsert again on the primary key “1”, the value for “Joe” will be overwritten:

 1$ ./immuclient exec "UPSERT INTO people(id, name, salary) VALUES (1, 'Joe', 20000);"
 2Updated rows: 1
 3
 4$ ./immuclient query "SELECT id, name, salary FROM people;"
 5+------------------------+--------------------------+----------------------------+
 6| (MYDATABASE PEOPLE ID) | (MYDATABASE PEOPLE NAME) | (MYDATABASE PEOPLE SALARY) |
 7+------------------------+--------------------------+----------------------------+
 8|                      1 | "Joe"                    |                      20000 |
 9|                      2 | "Bob"                    |                      30000 |
10+------------------------+--------------------------+----------------------------+

Time travel#

immudb is a immutable database. History is always preserved. With immudb you can travel in time!

1$ ./immuclient query "SELECT id, name, salary FROM people WHERE name='Joe';"
2+------------------------+--------------------------+----------------------------+
3| (MYDATABASE PEOPLE ID) | (MYDATABASE PEOPLE NAME) | (MYDATABASE PEOPLE SALARY) |
4+------------------------+--------------------------+----------------------------+
5|                      1 | "Joe"                    |                      20000 |
6+------------------------+--------------------------+----------------------------+

We can see the current transaction id using ‘current’:

1$ ./immuclient current
2database:       mydatabase
3txID:           5
4hash:           2986dfeb2d15e55d8189f08c2508318addabe9e773e0b6e329cf23b654cc22e7

This is the transaction id we will be using for the subsequent queries.

Eg. before the update:

1$ ./immuclient query "SELECT id, name, salary FROM people BEFORE TX 5 WHERE name='Joe';"
2+------------------------+--------------------------+----------------------------+
3| (MYDATABASE PEOPLE ID) | (MYDATABASE PEOPLE NAME) | (MYDATABASE PEOPLE SALARY) |
4+------------------------+--------------------------+----------------------------+
5|                      1 | "Joe"                    |                      10000 |
6+------------------------+--------------------------+----------------------------+

or even before the first time insert (guess what, it is empty!):

1$ ./immuclient query "SELECT id, name, salary FROM people BEFORE TX 1 WHERE name='Joe';"
2+------------------------+--------------------------+----------------------------+
3| (MYDATABASE PEOPLE ID) | (MYDATABASE PEOPLE NAME) | (MYDATABASE PEOPLE SALARY) |
4+------------------------+--------------------------+----------------------------+
5+------------------------+--------------------------+----------------------------+

You can even TABLE a table with itself in the past. Imagine you want to see how people salary changed between two points in time:

1$ ./immuclient query "SELECT peoplenow.id, peoplenow.name, peoplethen.salary, peoplenow.salary FROM people BEFORE TX 5 AS peoplethen INNER JOIN people AS peoplenow ON peoplenow.id=peoplethen.id;"
2+---------------------------+-----------------------------+--------------------------------+-------------------------------+
3| (MYDATABASE PEOPLENOW ID) | (MYDATABASE PEOPLENOW NAME) | (MYDATABASE PEOPLETHEN SALARY) | (MYDATABASE PEOPLENOW SALARY) |
4+---------------------------+-----------------------------+--------------------------------+-------------------------------+
5|                         1 | "Joe"                       |                          10000 |                         20000 |
6|                         2 | "Bob"                       |                          30000 |                         30000 |
7+---------------------------+-----------------------------+--------------------------------+-------------------------------+

KV Data revisions#

Whenever a new value is stored under given key, immudb saves a new revision of that data. Revision numbers start with 1 - the first value ever written to the database will have a revision number 1, the second will have 2 and so on.

When reading a value from immudb, an explicit revision number can be specified. If the provided number is greater than 0, a value for given revision is retrieved. If the provided number is less than 0, the nth previous value is retrieved.

 1$ ./immuclient set key value1
 2tx:       2
 3rev:      1
 4key:      key
 5value:    value1
 6
 7$ ./immuclient set key value2
 8tx:       3
 9rev:      2
10key:      key
11value:    value2
12
13$ ./immuclient set key value3
14tx:       4
15rev:      3
16key:      key
17value:    value3
18
19$ ./immuclient get key@1  # Get the key at the first revision
20tx:       2
21rev:      1
22key:      key
23value:    value1
24
25$ ./immuclient get key@-1  # Get the key at the previous revision
26tx:       3
27rev:      2
28key:      key
29value:    value2

The immuclient tool has also the possibility to restore a previous revision for given key.

1$ ./immuclient restore key@-2
2tx:       5
3rev:      4
4key:      key
5value:    value1

Querying for keys containing revision separator#

In some cases, the key can already contain the @ character reserved for key separator. In such case there are few options to read such key. The revision separator can be changed to any other string that is not part of the key. Also because immuclient will only scan the last occurrence of the revision separator, an explicit 0th revision can be set to read the current value behind such key.

 1$ ./immuclient set some@email.address active
 2tx:       2
 3rev:      1
 4key:      some@email.address
 5value:    active
 6
 7# Change the revision separator with environment variable
 8$ IMMUCLIENT_REVISION_SEPARATOR="###" ./immuclient get some@email.address
 9tx:     2
10key:    some@email.address
11value:  active
12hash:   138033b5a89438758fdb3481ba0dc44816d550749f799223587cb30cd7eadf5a
13
14# Disable / change the revision separator through command-line argument
15$ ./immuclient get --revision-separator="" some@email.address
16tx:       2
17rev:      1
18key:      some@email.address
19value:    active
20
21# Always use the revision number, use 0 for the current value
22$ ./immuclient get some@email.address@0
23tx:       2
24rev:      1
25key:      some@email.address
26value:    active
Edit this page on GitHub Last updated