# Getting started with immudb Development

This guide provides developers with the first steps of using immudb from their application and from their favourite programming language:

  • Connect to the database
  • Insert and retrieve data

TIP

To learn how to develop for immudb with Python in a guided online environment, visit the immudb Playground at https://play.codenotary.com (opens new window).

TIP

Examples used in this documentation can be found in immudb examples repository (opens new window).

# SDKs

In the most common scenario, you would perform write and read operations on the database talking to the server. In this case your application will be a client to immudb.

SDKs make it comfortable to talk to the server from your favorite language, without having to deal with details about how to talk to it.

The most well-known and recommended immudb SDK is written in Golang (opens new window), but there are other SDKs available, both maintained by the internal team and by the community.

Language Maintainer Immdb version link Notes
go immudb team 1.2.4 link (opens new window)
python immudb team 1.2.3 link (opens new window)
JAVA immudb team 1.2.1 link (opens new window) Verification is not working
NODE immudb team 1.2.1 link (opens new window) Verification is not working
JS immudb team 1.2.1 link (opens new window) Verification is not working
ruby Community (Ankane (opens new window)) 1.2.1 link (opens new window) Verification is not working

For other unsupported programming languages, immugw provides a REST gateway that can be used to talk to the server via generic HTTP.

The immudb server manages the requests from the outside world to the store. In order to insert or retrieve data, you need to talk with the server.

SDK Architecture

# Connecting from your programming language

# Importing the SDK

In order to use the SDK, you need to download and import the libraries:

# Connection and authentication

The first step is to connect to the database, which listens by default in port 3322 and authenticate using the default user and password (immudb / immudb):

Note: You can change the server default options using environment variables, flags or the immudb.toml configuration file.

# Tamperproof read and write

You can write with built-in cryptographic verification. The client implements the mathematical validations, while your application uses a traditional read or write function.

# SQL Operations with the Go SDK

immudb can be used as an SQL database, and SDKs allow you to quickly make use of it in your application. The sample code below shows how easy it can be.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/codenotary/immudb/pkg/api/schema"
	immudb "github.com/codenotary/immudb/pkg/client"
)

func main() {
	opts := immudb.DefaultOptions().
		WithAddress("localhost").
		WithPort(3322)

	client := immudb.NewClient().WithOptions(opts)
	err := client.OpenSession(context.TODO(), []byte(`immudb`), []byte(`immudb`), "defaultdb")
	if err != nil {
		log.Fatal(err)
	}

	// To perform SQL statements, use the SQLExec function, which takes a SQLExecRequest with a SQL operation:
	_, err = client.SQLExec(context.TODO(), `
	    BEGIN TRANSACTION;
	            CREATE TABLE people(id INTEGER, name VARCHAR[256], salary INTEGER, PRIMARY KEY id);
	            CREATE INDEX ON people(name);
	    COMMIT;
	    `,
		map[string]interface{}{},
	)
	if err != nil {
		log.Fatal(err)
	}

	// This is also how you perform inserts:
	_, err = client.SQLExec(context.TODO(),
		"UPSERT INTO people(id, name, salary) VALUES (@id, @name, @salary);",
		map[string]interface{}{"id": 1, "name": "Joe", "salary": 1000},
	)
	if err != nil {
		log.Fatal(err)
	}

	// Once you have data in the database, you can use the SQLQuery method of the client to query.
	// Both SQLQuery and SQLExec allows named parameters.
	// Just encode them as @param and pass map[string]{}interface as values:
	res, err := client.SQLQuery(context.TODO(),
		"SELECT t.id AS d, t.name FROM people AS t WHERE id <= 3 AND name = @name",
		map[string]interface{}{"name": "Joe"},
		true,
	)
	if err != nil {
		fmt.Printf("To tu ?")
		log.Fatal(err)
	}

	// res is of the type *schema.SQLQueryResult. In order to iterate over the results,
	// you iterate over res.Rows. On each iteration, the row r will have a member Values,
	// which you can iterate to get each column.
	for _, r := range res.Rows {
		for _, v := range r.Values {
			log.Printf("%s\n", schema.RenderValue(v.Value))
		}
	}
}