Skip to main content

CamusDB tutorial

CamusDB is an open-source NewSQL distributed database. It runs on one node, or on a cluster of several nodes. It gives an application a full relational engine, and not a thin layer of SQL over a key/value store.

CamusDB includes these capabilities:

This tutorial uses camus-cli, which is the interactive shell of SQL. It walks through the basic workflow, against a CamusDB node or a cluster that runs. The workflow has six steps:

  1. Create a database.
  2. Create a table.
  3. Insert some rows.
  4. Query the data.
  5. Add an index.
  6. Update a row, and delete one.

Start with Why CamusDB? for an overview at a higher level. That page explains the design of CamusDB as a distributed database of SQL.

Try it in your browser​

You can run the tutorial commands here before installing anything. The embedded playground starts with a pre-created playground database, but you can also create your own database and switch with the database selector. Click the examples in order, or edit the SQL and experiment.

WebAssembly

Run the tutorial here

This is the real CamusDB engine compiled to WebAssembly. It runs as a single in-memory node inside this browser tab.

Loading the engine...

The engine is loading. The first load downloads the WebAssembly runtime.

Single-node, in-memory engine. Data stays in this tab and resets on reload.

Video walkthrough​

Start CamusDB​

CamusDB ships as a global tool of .NET. Install the .NET runtime first. Then install the server, and start a standalone node:

$ dotnet tool install --global CamusDB.Server
$ camusdb

The camusdb command starts with its built-in defaults when no file of a configuration exists. It stores the data under the data directory of the user. It listens on the HTTP port 5095, and on the gRPC port 5096:

____ ____ ____
/ ___|__ _ _ __ ___ _ _ ___| _ \| __ )
| | / _` | '_ ` _ \| | | / __| | | | _ \
| |__| (_| | | | | | | |_| \__ \ |_| | |_) |
\____\__,_|_| |_| |_|\__,_|___/____/|____/

Configuration: built-in defaults (no configuration file found)
Data directory: /Users/runner/.local/share/camusdb

Update the installed server:

$ dotnet tool update --global CamusDB.Server

Run this command to create a configuration of a start, under your own ownership:

$ camusdb init

That command writes ~/.camusdb/config.yml. It also creates the default data directory. Edit the file. Then run camusdb again.

You can also start CamusDB with Docker:

$ docker run --rm \
-p 5095:5095 \
-p 5096:5096 \
-v camus-data:/data \
--name camusdb camusdb/camusdb:latest

Install the shell of SQL:

$ dotnet tool install --global CamusDB.SqlSh

Then open the shell of SQL, in another terminal:

$ camus-cli

An interactive prompt appears:

CamusDB SQL Shell 0.11.0

Connected to http://localhost:5096 over gRPC, database: (none)

camus>

Create a database​

You must create a database explicitly before you use it. Create a database. Then move the shell to it:

camus> CREATE DATABASE factory;
Query OK, 0 rows affected (00:00:00.0711685)

camus> use factory;
Database changed to factory

You can start the shell with camus-cli factory. You nevertheless still need the statement CREATE DATABASE factory;, at the first use of that name of a database.

Create a table​

Create a table for the records of a robot:

CREATE TABLE robots (
id OID PRIMARY KEY NOT NULL,
name STRING NOT NULL,
kind STRING NOT NULL,
year INT64 DEFAULT (2024)
);

The table holds four columns:

ColumnTypeNotes
idOIDPrimary key object id.
nameSTRINGRequired robot name.
kindSTRINGRequired category or model family.
yearINT64Optional year with a default value.

For an identifier of a UUID, use the native type UUID. Do not use a STRING. A UUID column stores a compact value of 128 bits. It also uses a smaller key of an index than the text of a UUID.

Inspect the schema​

Show the tables of the current database:

camus> show tables
┌────────┐
│ tables │
├────────┤
│ robots │
└────────┘
1 rows in set (00:00:00.0526560)

Show the columns of robots:

camus> show columns from robots
┌───────┬───────────┬──────┬─────┬─────────┬───────┐
│ Field │ Type │ Null │ Key │ Default │ Extra │
├───────┼───────────┼──────┼─────┼─────────┼───────┤
│ id │ Id │ NO │ PRI │ NULL │ │
│ name │ String │ NO │ │ NULL │ │
│ kind │ String │ NO │ │ NULL │ │
│ year │ Integer64 │ YES │ │ 2024 │ │
└───────┴───────────┴──────┴─────┴─────────┴───────┘
4 rows in set (00:00:00.0189059)

Three other commands of an inspection are useful:

DESCRIBE robots;
SHOW CREATE TABLE robots;
SHOW INDEX FROM robots;

Show the definition in SQL of the table:

camus> show create table robots;
┌────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Table │ Create Table │
├────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ robots │ CREATE TABLE `robots` ( `id` OID NOT NULL, `name` STRING NOT NULL, `kind` STRING NOT NULL, `year` INT64 NULL, PRIMARY KEY (`id`)); │
└────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
1 rows in set (00:00:00.0037082)

Insert rows​

Insert one row:

INSERT INTO robots (id, name, kind, year)
VALUES (GEN_ID(), "R2-D2", "utility", 1977);

Insert more than one row, with one statement:

INSERT INTO robots (id, name, kind, year)
VALUES
(GEN_ID(), "C-3PO", "protocol", 1977),
(GEN_ID(), "T-800", "android", 1984);

Use DEFAULT when CamusDB must apply the default of the column:

INSERT INTO robots (id, name, kind, year)
VALUES (GEN_ID(), "K-2SO", "security", DEFAULT);

Query rows​

Select the rows of the table:

camus> SELECT id, name, kind, year FROM robots ORDER BY year ASC;
┌──────────────────────────┬───────┬──────────┬──────┐
│ id │ name │ kind │ year │
├──────────────────────────┼───────┼──────────┼──────┤
│ 6a3dd713d615ae230488d7f2 │ R2-D2 │ utility │ 1977 │
│ 6a3dd71bd615ae230488d7f4 │ C-3PO │ protocol │ 1977 │
│ 6a3dd71bd615ae230488d7f5 │ T-800 │ android │ 1984 │
│ 6a3dd726d615ae230488d7f8 │ K-2SO │ security │ 2024 │
└──────────────────────────┴───────┴──────────┴──────┘
4 rows in set (00:00:00.0232238)

Filter the result with a WHERE clause:

camus> SELECT name, year FROM robots WHERE year >= 1980;
┌───────┬──────┐
│ name │ year │
├───────┼──────┤
│ T-800 │ 1984 │
│ K-2SO │ 2024 │
└───────┴──────┘
2 rows in set (00:00:00.0298712)

LIKE and ILIKE match a pattern:

camus> SELECT id, name FROM robots WHERE name ILIKE "r%";
┌──────────────────────────┬───────┐
│ id │ name │
├──────────────────────────┼───────┤
│ 6a3dd713d615ae230488d7f2 │ R2-D2 │
└──────────────────────────┴───────┘
1 rows in set (00:00:00.0254039)

Aggregate the rows:

SELECT COUNT(*) FROM robots;
SELECT MIN(year), MAX(year) FROM robots;

Create an index​

An index helps CamusDB. It then does not scan every row to find the matching data.

CREATE INDEX robots_kind_idx ON robots (kind);

Inspect the indexes:

SHOW INDEXES FROM robots;

Rename schema objects​

You can rename a table, and a column. CamusDB rewrites no data of a row:

ALTER TABLE robots RENAME COLUMN kind TO category;
ALTER TABLE robots RENAME TO machines;

Update rows​

An UPDATE in SQL needs a WHERE clause.

UPDATE machines
SET year = 1982
WHERE name = "T-800";

Confirm the change:

SELECT name, year
FROM machines
WHERE name = "T-800";

Delete rows​

A DELETE in SQL also needs a WHERE clause.

DELETE FROM machines
WHERE name = "K-2SO";

Column types​

SQL typeNotes
OIDNative object id values.
UUIDNative 128-bit UUID values. Prefer this over STRING for UUID identifiers.
INT64Signed 64-bit integers.
FLOAT64Double-precision floating point values.
FLOAT32Single-precision floating point values.
BOOLBoolean values.
STRING, STRING(N)Text values, optionally with a maximum length.
DATE, DATETIMECalendar dates and UTC instants.
BYTESOpaque byte strings.
ARRAY(T)Ordered lists of scalar values.

Continue with three pages: the SQL overview, Data Types, and Tables And Columns.

Then read SELECT for a filter, a group, and an order. Read Joins And Subqueries for a join, a subquery, and a derived table.