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

Queries & History

The fundamental property of immudb is that it’s an append-only database. This means that an update does not change an existing record. Instead, it is a new insert of the same key with a new value. It’s possible to retrieve all the values for a particular key with the history command.

History accepts the following parameters:

  • Key: a key of an item
  • Offset: the starting index (excluded from the search). Optional
  • Limit: maximum returned items. Optional
  • Desc: items are returned in reverse order. Optional
  • SinceTx: immudb will wait that the transaction specified by SinceTx is processed. Optional

Go

 1package main
 2
 3import (
 4	"context"
 5	"fmt"
 6	"log"
 7
 8	"github.com/codenotary/immudb/pkg/api/schema"
 9	immudb "github.com/codenotary/immudb/pkg/client"
10)
11
12func main() {
13	opts := immudb.DefaultOptions().
14		WithAddress("localhost").
15		WithPort(3322)
16
17	client := immudb.NewClient().WithOptions(opts)
18	err := client.OpenSession(
19		context.TODO(),
20		[]byte(`immudb`),
21		[]byte(`immudb`),
22		"defaultdb",
23	)
24	if err != nil {
25		log.Fatal(err)
26	}
27
28	defer client.CloseSession(context.TODO())
29
30	_, err = client.Set(
31		context.TODO(),
32		[]byte(`hello`),
33		[]byte(`immutable world`),
34	)
35	if err != nil {
36		log.Fatal(err)
37	}
38	_, err = client.Set(
39		context.TODO(),
40		[]byte(`hello`),
41		[]byte(`immudb`),
42	)
43	if err != nil {
44		log.Fatal(err)
45	}
46
47	req := &schema.HistoryRequest{
48		Key: []byte(`hello`),
49	}
50
51	ret, err := client.History(context.TODO(), req)
52	if err != nil {
53		log.Fatal(err)
54	}
55
56	fmt.Printf(
57		"Successfully retrieved %d entries for key %s\n",
58		len(ret.GetEntries()),
59		req.Key,
60	)
61}

Java

 1package io.codenotary.immudb.helloworld;
 2
 3import java.nio.charset.StandardCharsets;
 4import java.util.Arrays;
 5import java.util.Iterator;
 6
 7import io.codenotary.immudb4j.Entry;
 8import io.codenotary.immudb4j.FileImmuStateHolder;
 9import io.codenotary.immudb4j.ImmuClient;
10
11public class App {
12
13    public static void main(String[] args) {
14
15        ImmuClient client = null;
16
17        try {
18
19            FileImmuStateHolder stateHolder = FileImmuStateHolder.newBuilder()
20                    .withStatesFolder("./immudb_states")
21                    .build();
22
23            client = ImmuClient.newBuilder()
24                    .withServerUrl("127.0.0.1")
25                    .withServerPort(3322)
26                    .withStateHolder(stateHolder)
27                    .build();
28
29            client.openSession("defaultdb", "immudb", "immudb");
30
31            byte[] key1 = "myKey1".getBytes(StandardCharsets.UTF_8);
32            byte[] value1 = new byte[] { 1, 2, 3 };
33            byte[] value2 = new byte[] { 4, 5, 6 };
34
35            client.set(key1, value1);
36            client.set(key1, value2);
37
38            Iterator<Entry> it = client.history(key1, false, 0, 0);
39
40            while (it.hasNext()) {
41                Entry entry = it.next();
42
43                System.out.format("('%s', '%s')\n", new String(entry.getKey()), Arrays.toString(entry.getValue()));
44            }
45
46            client.closeSession();
47
48        } catch (Exception e) {
49            e.printStackTrace();
50        } finally {
51            if (client != null) {
52                try {
53                    client.shutdown();
54                } catch (InterruptedException e) {
55                    e.printStackTrace();
56                }
57            }
58        }
59
60    }
61
62}

Note that, similar with many other methods, history method is overloaded to allow different kinds/set of parameters.

.NET

 1
 2var client = new ImmuClient();
 3await client.Open("immudb", "immudb", "defaultdb");
 4
 5try
 6{
 7    await client.Set("history1", value1);
 8    await client.Set("history1", value2);
 9    await client.Set("history2", value1);
10    await client.Set("history2", value2);
11    await client.Set("history2", value3);
12}
13catch (CorruptedDataException e)
14{
15   Console.WriteLine("Failed at set.", e);
16}
17
18List<Entry> historyResponse1 = await client.History("history1", 10, 0, false);
19
20await client.Close();

Note that, similar with many other methods, history method is overloaded to allow different kinds/set of parameters.

Python

Python immudb sdk currently doesn’t support SinceTx parameter

 1from immudb import ImmudbClient
 2
 3URL = "localhost:3322"  # immudb running on your machine
 4LOGIN = "immudb"        # Default username
 5PASSWORD = "immudb"     # Default password
 6DB = b"defaultdb"       # Default database name (must be in bytes)
 7
 8def main():
 9    client = ImmudbClient(URL)
10    client.login(LOGIN, PASSWORD, database = DB)
11    
12    client.set(b'test', b'1')
13    client.set(b'test', b'2')
14    client.set(b'test', b'3')
15
16    history = client.history(b'test', 0, 100, True) # List[immudb.datatypes.historyResponseItem]
17    responseItemFirst = history[0]
18    print(responseItemFirst.key)    # Entry key (b'test')
19    print(responseItemFirst.value)  # Entry value (b'3')
20    print(responseItemFirst.tx)     # Transaction id
21    
22    responseItemThird = history[2]
23    print(responseItemThird.key)    # Entry key (b'test')
24    print(responseItemThird.value)  # Entry value (b'1')
25    print(responseItemThird.tx)     # Transaction id
26
27if __name__ == "__main__":
28    main()

Node.js

 1import ImmudbClient from 'immudb-node'
 2import Parameters from 'immudb-node/types/parameters'
 3
 4const IMMUDB_HOST = '127.0.0.1'
 5const IMMUDB_PORT = '3322'
 6const IMMUDB_USER = 'immudb'
 7const IMMUDB_PWD = 'immudb'
 8
 9const cl = new ImmudbClient({ host: IMMUDB_HOST, port: IMMUDB_PORT });
10
11(async () => {
12	await cl.login({ user: IMMUDB_USER, password: IMMUDB_PWD })
13	
14	const key = 'hello'
15
16	await cl.set({ key, value: 'immutable world' })
17	await cl.set({ key, value: 'immudb' })
18
19	const historyReq: Parameters.History = {
20		key
21	}
22	const historyRes = cl.history(historyReq)
23	console.log('success: history', historyRes)
24})()

Others

If you’re using another development language, please refer to the immugw option.


Counting#

Counting entries is not supported at the moment.

Go

This feature is not yet supported or not documented. Do you want to make a feature request or help out? Open an issue on Go sdk github project

Java

This feature is not yet supported or not documented. Do you want to make a feature request or help out? Open an issue on Java sdk github project

Python

This feature is not yet supported or not documented. Do you want to make a feature request or help out? Open an issue on Python sdk github project

Node.js

This feature is not yet supported or not documented. Do you want to make a feature request or help out? Open an issue on Node.js sdk github project

.NET

This feature is not yet supported or not documented. Do you want to make a feature request or help out? Open an issue on .Net sdk github project

Others

If you’re using another development language, please refer to the immugw option.


Scan#

The scan command is used to iterate over the collection of elements present in the currently selected database. Scan accepts the following parameters:

  • Prefix: prefix. If not provided all keys will be involved. Optional
  • SeekKey: initial key for the first entry in the iteration. Optional
  • Desc: DESC or ASC sorting order. Optional
  • Limit: maximum returned items. Optional
  • SinceTx: immudb will wait that the transaction provided by SinceTx be processed. Optional
  • NoWait: Default false. When true scan doesn’t wait for the index to be fully generated and returns the last indexed value. Optional

To gain speed it’s possible to specify noWait=true. The control will be returned to the caller immediately, without waiting for the indexing to complete. When noWait is used, keep in mind that the returned data may not be yet up to date with the inserted data, as the indexing might not have completed.

Go

An ordinary scan command and a reversed one.

 1package main
 2
 3import (
 4	"context"
 5	"fmt"
 6	"log"
 7	"math"
 8
 9	"github.com/codenotary/immudb/pkg/api/schema"
10	immudb "github.com/codenotary/immudb/pkg/client"
11)
12
13func main() {
14	opts := immudb.DefaultOptions().
15		WithAddress("localhost").
16		WithPort(3322)
17
18	client := immudb.NewClient().WithOptions(opts)
19	err := client.OpenSession(
20		context.TODO(),
21		[]byte(`immudb`),
22		[]byte(`immudb`),
23		"defaultdb",
24	)
25	if err != nil {
26		log.Fatal(err)
27	}
28
29	defer client.CloseSession(context.TODO())
30
31	_, err = client.Set(context.TODO(), []byte(`aaa`), []byte(`item1`))
32	if err != nil {
33		log.Fatal(err)
34	}
35	_, err = client.Set(context.TODO(), []byte(`bbb`), []byte(`item2`))
36	if err != nil {
37		log.Fatal(err)
38	}
39	_, err = client.Set(context.TODO(), []byte(`abc`), []byte(`item3`))
40	if err != nil {
41		log.Fatal(err)
42	}
43
44	scanReq := &schema.ScanRequest{
45		Prefix: []byte(`a`),
46	}
47
48	list, err := client.Scan(context.TODO(), scanReq)
49	if err != nil {
50		log.Fatal(err)
51	}
52	fmt.Printf("%v\n", list)
53	scanReq1 := &schema.ScanRequest{
54		SeekKey: []byte{0xFF},
55		Prefix:  []byte(`a`),
56		Desc:    true,
57	}
58
59	list, err = client.Scan(context.TODO(), scanReq1)
60	if err != nil {
61		log.Fatal(err)
62	}
63	fmt.Printf("%v\n", list)
64
65	// scan on all key  values on the current database,
66	// with a fresh snapshot
67	scanReq2 := &schema.ScanRequest{
68		SeekKey: []byte{0xFF},
69		Desc:    true,
70		SinceTx: math.MaxUint64,
71	}
72
73	list, err = client.Scan(context.TODO(), scanReq2)
74	if err != nil {
75		log.Fatal(err)
76	}
77	fmt.Printf("%v\n", list)
78}

Java

 1package io.codenotary.immudb.helloworld;
 2
 3import java.nio.charset.StandardCharsets;
 4import java.util.Arrays;
 5import java.util.Iterator;
 6
 7import io.codenotary.immudb4j.Entry;
 8import io.codenotary.immudb4j.FileImmuStateHolder;
 9import io.codenotary.immudb4j.ImmuClient;
10
11public class App {
12
13    public static void main(String[] args) {
14
15        ImmuClient client = null;
16
17        try {
18
19            FileImmuStateHolder stateHolder = FileImmuStateHolder.newBuilder()
20                    .withStatesFolder("./immudb_states")
21                    .build();
22
23            client = ImmuClient.newBuilder()
24                    .withServerUrl("127.0.0.1")
25                    .withServerPort(3322)
26                    .withStateHolder(stateHolder)
27                    .build();
28
29            client.openSession("defaultdb", "immudb", "immudb");
30
31            byte[] key1 = "myKey1".getBytes(StandardCharsets.UTF_8);
32            byte[] value1 = new byte[] { 1, 2, 3 };
33
34            byte[] key2 = "myKey2".getBytes(StandardCharsets.UTF_8);
35            byte[] value2 = new byte[] { 4, 5, 6 };
36
37            client.set(key1, value1);
38            client.set(key2, value2);
39
40            Iterator<Entry> it = client.scan("myKey");
41
42            while (it.hasNext()) {
43                Entry entry = it.next();
44
45                System.out.format("('%s', '%s')\n", new String(entry.getKey()), Arrays.toString(entry.getValue()));
46            }
47
48            client.closeSession();
49
50        } catch (Exception e) {
51            e.printStackTrace();
52        } finally {
53            if (client != null) {
54                try {
55                    client.shutdown();
56                } catch (InterruptedException e) {
57                    e.printStackTrace();
58                }
59            }
60        }
61
62    }
63
64}

scan is an overloaded method, therefore multiple flavours of it with different parameter options exist.

.NET

 1var client = new ImmuClient();
 2await client.Open("immudb", "immudb", "defaultdb");
 3
 4byte[] value1 = { 0, 1, 2, 3 };
 5byte[] value2 = { 4, 5, 6, 7 };
 6
 7try
 8{
 9    await client.Set("scan1", value1);
10    await client.Set("scan2", value2);
11}
12catch (CorruptedDataException e)
13{
14    Assert.Fail("Failed at set.", e);
15}
16
17List<Entry> scanResult = await client.Scan("scan", 5, false);
18Console.WriteLine(scanResult.Count);
19
20await client.Close();

scan is an overloaded method, therefore multiple flavours of it with different parameter options exist.

Python

 1from immudb import ImmudbClient
 2
 3URL = "localhost:3322"  # immudb running on your machine
 4LOGIN = "immudb"        # Default username
 5PASSWORD = "immudb"     # Default password
 6DB = b"defaultdb"       # Default database name (must be in bytes)
 7
 8def main():
 9    client = ImmudbClient(URL)
10    client.login(LOGIN, PASSWORD, database = DB)
11    toSet = {
12        b"aaa": b'1',
13        b'bbb': b'2',
14        b'ccc': b'3',
15        b'acc': b'1',
16        b'aac': b'2',
17        b'aac:test1': b'3',
18        b'aac:test2': b'1',
19        b'aac:xxx:test': b'2'
20    }
21    client.setAll(toSet)
22    
23    result = client.scan(b'', b'', True, 100) # All entries
24    print(result)
25    result = client.scan(b'', b'aac', True, 100) # All entries with prefix 'aac' including 'aac'
26    print(result)
27
28    # Seek key example (allows retrieve entries in proper chunks):
29    result = client.scan(b'', b'', False, 3)
30    while result:
31        for item, value in result.items():
32            print("SEEK", item, value)
33        lastKey = list(result.keys())[-1]
34        result = client.scan(lastKey, b'', False, 3)
35
36if __name__ == "__main__":
37    main()

Node.js

 1import ImmudbClient from 'immudb-node'
 2import Parameters from 'immudb-node/types/parameters'
 3
 4const IMMUDB_HOST = '127.0.0.1'
 5const IMMUDB_PORT = '3322'
 6const IMMUDB_USER = 'immudb'
 7const IMMUDB_PWD = 'immudb'
 8
 9const cl = new ImmudbClient({ host: IMMUDB_HOST, port: IMMUDB_PORT });
10
11(async () => {
12	await cl.login({ user: IMMUDB_USER, password: IMMUDB_PWD })
13	
14	await cl.set({ key: 'aaa', value: 'item1' })
15	await cl.set({ key: 'bbb', value: 'item2' })
16	await cl.set({ key: 'abc', value: 'item3' })
17
18	const scanReq: Parameters.Scan = {
19		prefix: 'a',
20		desc: false,
21		limit: 0,
22		sincetx: 0
23	}
24	const scanRes = await cl.scan(scanReq)
25	console.log('success: scan', scanRes)
26
27	const scanReq1: Parameters.Scan = {
28		prefix: 'a',
29		desc: true,
30		limit: 0,
31		sincetx: 0
32	}
33	const scanRes1 = await cl.scan(scanReq1)
34	console.log('success: scan', scanRes1)
35})()

Example with an offset:

 1import ImmudbClient from 'immudb-node'
 2import Parameters from 'immudb-node/types/parameters'
 3
 4const IMMUDB_HOST = '127.0.0.1'
 5const IMMUDB_PORT = '3322'
 6const IMMUDB_USER = 'immudb'
 7const IMMUDB_PWD = 'immudb'
 8
 9const cl = new ImmudbClient({ host: IMMUDB_HOST, port: IMMUDB_PORT });
10
11(async () => {
12	await cl.login({ user: IMMUDB_USER, password: IMMUDB_PWD })
13	
14	await cl.set({ key: 'aaa', value: 'item1' })
15	await cl.set({ key: 'bbb', value: 'item2' })
16	await cl.set({ key: 'abc', value: 'item3' })
17
18	const scanReq: Parameters.Scan = {
19		seekkey: '',
20		prefix: '',
21		desc: true,
22		limit: 0,
23		sincetx: 0
24	}
25	const scanRes = await cl.scan(scanReq)
26	console.log('success: scan', scanRes)
27
28	const scanReq1: Parameters.Scan = {
29		seekkey: 'bbb',
30		prefix: '',
31		desc: true,
32		limit: 0,
33		sincetx: 0
34	}
35	const scanRes1 = await cl.scan(scanReq1)
36	console.log('success: scan', scanRes1)
37
38	const scanReq2: Parameters.Scan = {
39		seekkey: 'b',
40		prefix: 'b',
41		desc: true,
42		limit: 0,
43		sincetx: 0
44	}
45	const scanRes2 = await cl.scan(scanReq2)
46	console.log('success: scan', scanRes2)
47})()

Others

If you’re using another development language, please refer to the immugw option.


References#

SetReference is like a “tag” operation. It appends a reference on a key/value element. As a consequence, when we retrieve that reference with a Get or VerifiedGet the value retrieved will be the original value associated with the original key. Its VerifiedReference counterpart is the same except that it also produces the inclusion and consistency proofs.

Go

 1package main
 2
 3import (
 4	"context"
 5	"fmt"
 6	"log"
 7
 8	immudb "github.com/codenotary/immudb/pkg/client"
 9)
10
11func main() {
12	opts := immudb.DefaultOptions().
13		WithAddress("localhost").
14		WithPort(3322)
15
16	client := immudb.NewClient().WithOptions(opts)
17	err := client.OpenSession(
18		context.TODO(),
19		[]byte(`immudb`),
20		[]byte(`immudb`),
21		"defaultdb",
22	)
23	if err != nil {
24		log.Fatal(err)
25	}
26
27	defer client.CloseSession(context.TODO())
28
29	_, err = client.Set(
30		context.TODO(),
31		[]byte(`firstKey`),
32		[]byte(`firstValue`),
33	)
34	if err != nil {
35		log.Fatal(err)
36	}
37	reference, err := client.SetReference(
38		context.TODO(),
39		[]byte(`myTag`),
40		[]byte(`firstKey`),
41	)
42	if err != nil {
43		log.Fatal(err)
44	}
45
46	fmt.Printf("%v\n", reference)
47	firstItem, err := client.Get(
48		context.TODO(),
49		[]byte(`myTag`),
50	)
51	if err != nil {
52		log.Fatal(err)
53	}
54	fmt.Printf("%v\n", firstItem)
55}

Example with verifications

 1package main
 2
 3import (
 4	"context"
 5	"fmt"
 6	"log"
 7
 8	immudb "github.com/codenotary/immudb/pkg/client"
 9)
10
11func main() {
12	opts := immudb.DefaultOptions().
13		WithAddress("localhost").
14		WithPort(3322)
15
16	client := immudb.NewClient().WithOptions(opts)
17	err := client.OpenSession(
18		context.TODO(),
19		[]byte(`immudb`),
20		[]byte(`immudb`),
21		"defaultdb",
22	)
23	if err != nil {
24		log.Fatal(err)
25	}
26
27	defer client.CloseSession(context.TODO())
28
29	_, err = client.Set(
30		context.TODO(),
31		[]byte(`secondKey`),
32		[]byte(`secondValue`),
33	)
34	if err != nil {
35		log.Fatal(err)
36	}
37	reference, err := client.VerifiedSetReference(
38		context.TODO(),
39		[]byte(`mySecondTag`),
40		[]byte(`secondKey`),
41	)
42	if err != nil {
43		log.Fatal(err)
44	}
45	fmt.Printf("%v\n", reference)
46
47	secondItem, err := client.Get(
48		context.TODO(),
49		[]byte(`mySecondTag`),
50	)
51	if err != nil {
52		log.Fatal(err)
53	}
54	fmt.Printf("%v\n", secondItem)
55}

Java

 1package io.codenotary.immudb.helloworld;
 2
 3import java.nio.charset.StandardCharsets;
 4import java.util.Arrays;
 5
 6import io.codenotary.immudb4j.Entry;
 7import io.codenotary.immudb4j.FileImmuStateHolder;
 8import io.codenotary.immudb4j.ImmuClient;
 9
10public class App {
11
12    public static void main(String[] args) {
13
14        ImmuClient client = null;
15
16        try {
17
18            FileImmuStateHolder stateHolder = FileImmuStateHolder.newBuilder()
19                    .withStatesFolder("./immudb_states")
20                    .build();
21
22            client = ImmuClient.newBuilder()
23                    .withServerUrl("127.0.0.1")
24                    .withServerPort(3322)
25                    .withStateHolder(stateHolder)
26                    .build();
27
28            client.openSession("defaultdb", "immudb", "immudb");
29
30            byte[] key = "myKey".getBytes(StandardCharsets.UTF_8);
31            byte[] value = new byte[] { 1, 2, 3 };
32
33            byte[] myRef = "myRef".getBytes(StandardCharsets.UTF_8);
34            
35            client.set(key, value);
36
37            client.setReference(myRef, key);
38
39            Entry entry = client.get(myRef);
40
41            System.out.format("('%s', '%s')\n", new String(entry.getKey()), Arrays.toString(entry.getValue()));
42            
43            client.closeSession();
44
45        } catch (Exception e) {
46            e.printStackTrace();
47        } finally {
48            if (client != null) {
49                try {
50                    client.shutdown();
51                } catch (InterruptedException e) {
52                    e.printStackTrace();
53                }
54            }
55        }
56
57    }
58
59}

.NET

 1var client = new ImmuClient();
 2await client.Open("immudb", "immudb", "defaultdb");
 3
 4byte[] key = Encoding.UTF8.GetBytes("testRef");
 5byte[] val = Encoding.UTF8.GetBytes("abc");
 6
 7TxHeader? setTxHdr = null;
 8try
 9{
10    setTxHdr = await client.Set(key, val);
11}
12catch (CorruptedDataException e)
13{
14    Console.WriteLine("Failed at set.", e);
15    return;
16}
17
18byte[] ref1Key = Encoding.UTF8.GetBytes("ref1_to_testRef");
19byte[] ref2Key = Encoding.UTF8.GetBytes("ref2_to_testRef");
20
21TxHeader? ref1TxHdr = null;
22try
23{
24    ref1TxHdr = await client.SetReference(ref1Key, key);
25}
26catch (CorruptedDataException e)
27{
28    Console.WriteLine("Failed at setReference", e);
29    return;
30}
31
32TxHeader? ref2TxHdr = null;
33try
34{
35    ref2TxHdr = await client.SetReference(ref2Key, key, setTxHdr.Id);
36}
37catch (CorruptedDataException e)
38{
39    Console.WriteLine("Failed at setReferenceAt.", e);
40}
41
42await client.Close();

Python

 1from immudb import ImmudbClient
 2
 3URL = "localhost:3322"  # immudb running on your machine
 4LOGIN = "immudb"        # Default username
 5PASSWORD = "immudb"     # Default password
 6DB = b"defaultdb"       # Default database name (must be in bytes)
 7
 8def main():
 9    client = ImmudbClient(URL)
10    client.login(LOGIN, PASSWORD, database = DB)
11    client.verifiedSet(b'x', b'1') 
12    client.verifiedSet(b'y', b'1') 
13    retrieved = client.verifiedGet(b'x') 
14    print(retrieved.refkey)     # Entry reference key (None)
15
16    client.verifiedSetReference(b'x', b'reference1')
17    client.setReference(b'x', b'reference2')
18    client.setReference(b'y', b'reference2')
19    client.verifiedSet(b'y', b'2') 
20
21    retrieved = client.verifiedGet(b'reference1')
22    print(retrieved.key)        # Entry key (b'x')
23    print(retrieved.refkey)     # Entry reference key (b'reference1')
24    print(retrieved.verified)   # Entry verification status (True)
25
26    retrieved = client.verifiedGet(b'reference2')
27    print(retrieved.key)        # Entry key (b'y')
28    print(retrieved.refkey)     # Entry reference key (b'reference2')
29    print(retrieved.verified)   # Entry verification status (True)
30    print(retrieved.value)      # Entry value (b'3')
31
32    retrieved = client.verifiedGet(b'x')
33    print(retrieved.key)        # Entry key (b'x')
34    print(retrieved.refkey)     # Entry reference key (None)
35    print(retrieved.verified)   # Entry verification status (True)
36
37    retrieved = client.get(b'reference2')
38    print(retrieved.key)        # Entry key (b'y')
39
40if __name__ == "__main__":
41    main()

Node.js

 1import ImmudbClient from 'immudb-node'
 2import Parameters from 'immudb-node/types/parameters'
 3
 4const IMMUDB_HOST = '127.0.0.1'
 5const IMMUDB_PORT = '3322'
 6const IMMUDB_USER = 'immudb'
 7const IMMUDB_PWD = 'immudb'
 8
 9const cl = new ImmudbClient({ host: IMMUDB_HOST, port: IMMUDB_PORT });
10
11(async () => {
12	await cl.login({ user: IMMUDB_USER, password: IMMUDB_PWD })
13	
14	const setReq: Parameters.Set = {
15		key: 'firstKey',
16		value: 'firstValue'
17	}
18	await cl.set(setReq)
19
20	const referenceReq: Parameters.SetReference = {
21		key: 'myTag',
22		referencedKey: 'firstKey'
23	}
24	const referenceRes = await cl.setReference(referenceReq)
25	console.log('success: setReference', referenceRes)
26
27	const getReq: Parameters.Get = {
28		key: 'myTag'
29	}
30	const getRes = await cl.get(getReq)
31	console.log('success: get by reference', getRes)
32})()

Example with verifications

 1import ImmudbClient from 'immudb-node'
 2import Parameters from 'immudb-node/types/parameters'
 3
 4const IMMUDB_HOST = '127.0.0.1'
 5const IMMUDB_PORT = '3322'
 6const IMMUDB_USER = 'immudb'
 7const IMMUDB_PWD = 'immudb'
 8
 9const cl = new ImmudbClient({ host: IMMUDB_HOST, port: IMMUDB_PORT });
10
11(async () => {
12	await cl.login({ user: IMMUDB_USER, password: IMMUDB_PWD })
13	
14	const setReq: Parameters.Set = {
15		key: 'firstKey',
16		value: 'firstValue'
17	}
18	await cl.set(setReq)
19
20	const verifiedReferenceReq: Parameters.SetReference = {
21		key: 'myTag',
22		referencedKey: 'firstKey'
23	}
24	const verifiedReferenceRes = await cl.verifiedSetReference(verifiedReferenceReq)
25	console.log('success: verifiedSetReference', verifiedReferenceRes)
26
27	const getReq: Parameters.Get = {
28		key: 'myTag'
29	}
30	const getRes = await cl.get(getReq)
31	console.log('success: get by reference', getRes)
32})()

Others

If you’re using another development language, please refer to the immugw option.

GetReference and VerifiedGetReference#

When reference is resolved with get or verifiedGet in case of multiples equals references the last reference is returned.

Go

 1package main
 2
 3import (
 4	"context"
 5	"fmt"
 6	"log"
 7
 8	immudb "github.com/codenotary/immudb/pkg/client"
 9)
10
11func main() {
12	opts := immudb.DefaultOptions().
13		WithAddress("localhost").
14		WithPort(3322)
15
16	client := immudb.NewClient().WithOptions(opts)
17	err := client.OpenSession(
18		context.TODO(),
19		[]byte(`immudb`),
20		[]byte(`immudb`),
21		"defaultdb",
22	)
23	if err != nil {
24		log.Fatal(err)
25	}
26
27	defer client.CloseSession(context.TODO())
28
29	_, err = client.Set(
30		context.TODO(),
31		[]byte(`secondKey`),
32		[]byte(`secondValue`),
33	)
34	if err != nil {
35		log.Fatal(err)
36	}
37	_, err = client.Set(
38		context.TODO(),
39		[]byte(`secondKey`),
40		[]byte(`thirdValue`),
41	)
42	if err != nil {
43		log.Fatal(err)
44	}
45	reference, err := client.VerifiedSetReference(
46		context.TODO(),
47		[]byte(`myThirdTag`),
48		[]byte(`secondKey`),
49	)
50	if err != nil {
51		log.Fatal(err)
52	}
53	fmt.Printf("%v\n", reference)
54
55	thirdItem, err := client.Get(
56		context.TODO(),
57		[]byte(`myThirdTag`),
58	)
59	if err != nil {
60		log.Fatal(err)
61	}
62	fmt.Printf("%v\n", thirdItem)
63}

Java

 1package io.codenotary.immudb.helloworld;
 2
 3import java.nio.charset.StandardCharsets;
 4import java.util.Arrays;
 5
 6import io.codenotary.immudb4j.Entry;
 7import io.codenotary.immudb4j.FileImmuStateHolder;
 8import io.codenotary.immudb4j.ImmuClient;
 9
10public class App {
11
12    public static void main(String[] args) {
13
14        ImmuClient client = null;
15
16        try {
17
18            FileImmuStateHolder stateHolder = FileImmuStateHolder.newBuilder()
19                    .withStatesFolder("./immudb_states")
20                    .build();
21
22            client = ImmuClient.newBuilder()
23                    .withServerUrl("127.0.0.1")
24                    .withServerPort(3322)
25                    .withStateHolder(stateHolder)
26                    .build();
27
28            client.openSession("defaultdb", "immudb", "immudb");
29
30            byte[] key = "myKey".getBytes(StandardCharsets.UTF_8);
31            byte[] value1 = new byte[] { 1, 2, 3 };
32            byte[] value2 = new byte[] { 4, 5, 6 };
33
34            client.set(key, value1);
35
36            byte[] myRef = "myRef".getBytes(StandardCharsets.UTF_8);
37            client.setReference(myRef, key);
38
39            client.set(key, value2);
40
41            Entry entry = client.get(myRef);
42
43            System.out.format("('%s', '%s')\n", new String(entry.getKey()), Arrays.toString(entry.getValue()));
44            
45            client.closeSession();
46
47        } catch (Exception e) {
48            e.printStackTrace();
49        } finally {
50            if (client != null) {
51                try {
52                    client.shutdown();
53                } catch (InterruptedException e) {
54                    e.printStackTrace();
55                }
56            }
57        }
58
59    }
60
61}

Python

 1from immudb import ImmudbClient
 2
 3URL = "localhost:3322"  # immudb running on your machine
 4LOGIN = "immudb"        # Default username
 5PASSWORD = "immudb"     # Default password
 6DB = b"defaultdb"       # Default database name (must be in bytes)
 7
 8def main():
 9    client = ImmudbClient(URL)
10    client.login(LOGIN, PASSWORD, database = DB)
11    client.verifiedSet(b'x', b'1') 
12    client.verifiedSet(b'y', b'1') 
13    retrieved = client.verifiedGet(b'x') 
14    print(retrieved.refkey)     # Entry reference key (None)
15
16    client.verifiedSetReference(b'x', b'reference1')
17    client.setReference(b'x', b'reference2')
18    client.setReference(b'y', b'reference2')
19    client.verifiedSet(b'y', b'2') 
20
21    retrieved = client.verifiedGet(b'reference1')
22    print(retrieved.key)        # Entry key (b'x')
23    print(retrieved.refkey)     # Entry reference key (b'reference1')
24    print(retrieved.verified)   # Entry verification status (True)
25
26    retrieved = client.verifiedGet(b'reference2')
27    print(retrieved.key)        # Entry key (b'y')
28    print(retrieved.refkey)     # Entry reference key (b'reference2')
29    print(retrieved.verified)   # Entry verification status (True)
30    print(retrieved.value)      # Entry value (b'3')
31
32    retrieved = client.verifiedGet(b'x')
33    print(retrieved.key)        # Entry key (b'x')
34    print(retrieved.refkey)     # Entry reference key (None)
35    print(retrieved.verified)   # Entry verification status (True)
36
37    retrieved = client.get(b'reference2')
38    print(retrieved.key)        # Entry key (b'y')
39
40if __name__ == "__main__":
41    main()

Node.js

 1import ImmudbClient from 'immudb-node'
 2import Parameters from 'immudb-node/types/parameters'
 3
 4const IMMUDB_HOST = '127.0.0.1'
 5const IMMUDB_PORT = '3322'
 6const IMMUDB_USER = 'immudb'
 7const IMMUDB_PWD = 'immudb'
 8
 9const cl = new ImmudbClient({ host: IMMUDB_HOST, port: IMMUDB_PORT });
10
11(async () => {
12	await cl.login({ user: IMMUDB_USER, password: IMMUDB_PWD })
13	
14	const setReq: Parameters.Set = {
15		key: 'firstKey',
16		value: 'firstValue'
17	}
18	await cl.set(setReq)
19	const setReq1: Parameters.Set = {
20		key: 'secondKey',
21		value: 'secondValue'
22	}
23	await cl.set(setReq1)
24
25	const verifiedReferenceReq: Parameters.SetReference = {
26		key: 'myTag',
27		referencedKey: 'firstKey'
28	}
29	await cl.verifiedSetReference(verifiedReferenceReq)
30	const verifiedReferenceReq1: Parameters.SetReference = {
31		key: 'myTag',
32		referencedKey: 'secondKey'
33	}
34	await cl.verifiedSetReference(verifiedReferenceReq1)
35
36	const getReq: Parameters.Get = {
37		key: 'myTag'
38	}
39	const getSecondItemRes = await cl.get(getReq)
40	console.log('success: get by second reference', getSecondItemRes)
41})()

.NET

 1
 2using ImmuDB;
 3using ImmuDB.Exceptions;
 4using ImmuDB.SQL;
 5
 6namespace simple_app;
 7
 8class Program
 9{
10    public static async Task Main(string[] args)
11    {
12      var client = new ImmuClient();
13
14      await client.Open("immudb", "immudb","defaultdb");
15      await client.VerifiedSet("mykey", "myvalue");
16      await client.VerifiedSetReference("myreference", "mykey");
17      Entry result = await client.Get("myreference");
18
19      System.Console.WriteLine(result.ToString());
20    }
21}

Others

If you’re using another development language, please refer to the immugw option.

Resolving reference with transaction id#

It’s possible to bind a reference to a key on a specific transaction using SetReferenceAt and VerifiedSetReferenceAt

Go

 1package main
 2
 3import (
 4	"context"
 5	"fmt"
 6	"log"
 7
 8	immudb "github.com/codenotary/immudb/pkg/client"
 9)
10
11func main() {
12	opts := immudb.DefaultOptions().
13		WithAddress("localhost").
14		WithPort(3322)
15
16	client := immudb.NewClient().WithOptions(opts)
17	err := client.OpenSession(
18		context.TODO(),
19		[]byte(`immudb`),
20		[]byte(`immudb`),
21		"defaultdb",
22	)
23	if err != nil {
24		log.Fatal(err)
25	}
26
27	defer client.CloseSession(context.TODO())
28
29	meta, err := client.Set(
30		context.TODO(),
31		[]byte(`secondKey`),
32		[]byte(`secondValue`),
33	)
34	if err != nil {
35		log.Fatal(err)
36	}
37	_, err = client.Set(
38		context.TODO(),
39		[]byte(`secondKey`),
40		[]byte(`thirdValue`),
41	)
42	if err != nil {
43		log.Fatal(err)
44	}
45	reference, err := client.VerifiedSetReferenceAt(
46		context.TODO(),
47		[]byte(`myThirdTag`),
48		[]byte(`secondKey`),
49		meta.Id,
50	)
51	if err != nil {
52		log.Fatal(err)
53	}
54	fmt.Printf("%v\n", reference)
55
56	thirdItem, err := client.Get(
57		context.TODO(),
58		[]byte(`myThirdTag`),
59	)
60	if err != nil {
61		log.Fatal(err)
62	}
63	fmt.Printf("%v\n", thirdItem)
64}

Java

 1package io.codenotary.immudb.helloworld;
 2
 3import java.nio.charset.StandardCharsets;
 4import java.util.Arrays;
 5
 6import io.codenotary.immudb4j.Entry;
 7import io.codenotary.immudb4j.FileImmuStateHolder;
 8import io.codenotary.immudb4j.ImmuClient;
 9import io.codenotary.immudb4j.TxHeader;
10
11public class App {
12
13    public static void main(String[] args) {
14
15        ImmuClient client = null;
16
17        try {
18
19            FileImmuStateHolder stateHolder = FileImmuStateHolder.newBuilder()
20                    .withStatesFolder("./immudb_states")
21                    .build();
22
23            client = ImmuClient.newBuilder()
24                    .withServerUrl("127.0.0.1")
25                    .withServerPort(3322)
26                    .withStateHolder(stateHolder)
27                    .build();
28
29            client.openSession("defaultdb", "immudb", "immudb");
30
31            byte[] key = "myKey".getBytes(StandardCharsets.UTF_8);
32            byte[] value1 = new byte[] { 1, 2, 3 };
33            byte[] value2 = new byte[] { 4, 5, 6 };
34
35            TxHeader hdr1 = client.set(key, value1);
36
37            byte[] myRef = "myRef".getBytes(StandardCharsets.UTF_8);
38            client.setReference(myRef, key, hdr1.getId());
39
40            client.set(key, value2);
41
42            Entry entry = client.get(myRef);
43
44            System.out.format("('%s', '%s')\n", new String(entry.getKey()), Arrays.toString(entry.getValue()));
45            
46            client.closeSession();
47
48        } catch (Exception e) {
49            e.printStackTrace();
50        } finally {
51            if (client != null) {
52                try {
53                    client.shutdown();
54                } catch (InterruptedException e) {
55                    e.printStackTrace();
56                }
57            }
58        }
59
60    }
61
62}

.NET

 1
 2var client = new ImmuClient();
 3await client.Open("immudb", "immudb", "defaultdb");
 4
 5byte[] key = Encoding.UTF8.GetBytes("testRef");
 6byte[] val = Encoding.UTF8.GetBytes("abc");
 7
 8TxHeader? setTxHdr = null;
 9try
10{
11    setTxHdr = await client.Set(key, val);
12}
13catch (CorruptedDataException e)
14{
15    Console.WriteLine("Failed at set.", e);
16    return;
17}
18
19byte[] ref1Key = Encoding.UTF8.GetBytes("ref1_to_testRef");
20byte[] ref2Key = Encoding.UTF8.GetBytes("ref2_to_testRef");
21
22TxHeader? ref1TxHdr = null;
23try
24{
25    ref1TxHdr = await client.SetReference(ref1Key, key);
26}
27catch (CorruptedDataException e)
28{
29    Console.WriteLine("Failed at SetReference", e);
30    return;
31}
32
33TxHeader? ref2TxHdr = null;
34try
35{
36    ref2TxHdr = await client.SetReference(ref2Key, key, setTxHdr.Id);
37}
38catch (CorruptedDataException e)
39{
40    Console.WriteLine("Failed at SetReference.", e);
41}
42
43await client.Close();

Python

This feature is not yet supported or not documented. Do you want to make a feature request or help out? Open an issue on Python sdk github project

Node.js

 1import ImmudbClient from 'immudb-node'
 2import Parameters from 'immudb-node/types/parameters'
 3
 4const IMMUDB_HOST = '127.0.0.1'
 5const IMMUDB_PORT = '3322'
 6const IMMUDB_USER = 'immudb'
 7const IMMUDB_PWD = 'immudb'
 8
 9const cl = new ImmudbClient({ host: IMMUDB_HOST, port: IMMUDB_PORT });
10
11(async () => {
12	await cl.login({ user: IMMUDB_USER, password: IMMUDB_PWD })
13
14	const { id } = await cl.set({ key: 'firstKey', value: 'firstValue' })
15	await cl.set({ key: 'firstKey', value: 'secondValue' })
16
17	const verifiedSetReferenceAtReq: Parameters.VerifiedSetReferenceAt = {
18		key: 'myFirstTag',
19		referencedKey: 'firstKey',
20		attx: id
21	}
22	const verifiedSetReferenceAtRes = await cl.verifiedSetReferenceAt(verifiedSetReferenceAtReq)
23	console.log('success: verifiedSetReferenceAt', verifiedSetReferenceAtRes)
24
25	const getSecondItemRes = await cl.get({ key: 'myFirstTag' })
26	console.log('success: get second item by reference', getSecondItemRes)
27})()

Others

If you’re using another development language, please refer to the immugw option.

Edit this page on GitHub Last updated