A Tour of GetSetDB

Manan
9 min readJan 6, 2019

GetSetDB is an open source No-SQL database inspired by Redis which is another No-SQL database that lives in memory for caching. GetSetDB was started as a simple project for my Computer Science course in high school but after I saw its potential in the real world, I rewrote the entire code-base from scratch from C++ to Go simply because I found socket programming and supporting concurrent clients to be too difficult in C. GetSetDB can be found on Github where some official and some unofficial connectors for different languages and platforms also reside although at the time of writing only Python is supported. Connectors for Go, Ruby and Perl are in active development as well. This post aims to be an introduction to GetSetDB — explaining all its internal working and usage.

GetSetDB draws heavy inspiration from Redis and other key-value pair databases like Google’s LevelDB and BerkleyDB, as mentioned before, but there are a few core difference between the working and design of GetSetDB that sets it apart from those databases. You don’t have to be familiar with Redis to understand GetSetDB but if you are then you’ll find a ton of similarities and some key changes that hope to improve upon Redis. To get started with GetSetDB, you first need to install it. Instructions can be found here.

Now that you’ve installed GetSetDB on your system, you should be able to run it with just a simple command in the terminal —

$ getsetdb      ___     _   ___      _   ___  ___ 
/ __|___| |_/ __| ___| |_| \| _ )
| (_ / -_) _\__ \/ -_) _| |) | _ \
\___\___|\__|___/\___|\__|___/|___/

2019/01/05 23:57:19 tcp server running on 127.0.0.1:4998

It’ll display the cool GetSetDB banner and logs the port it’s running on which is 4998.

Now before we get into typing commands or anything, let’s talk about how GetSetDB is structured. Take a look at this diagram —

an illustration of how GetSetDB is organised

Let’s talk about the GetSetDB server first — after all, that’s the only thing that’s useful to us. The server just contains a big empty space in the beginning that simply referred to as “the Space”. Space is like the home of all the “Databases” that live in it. We can compare this to how MySQL stores its “databases” or how MongoDB stores its “collections” — the Space stores all the Databases. Now this is the first major difference between GetSetDB and Redis — the latter has no concept of separating its pairs — everything is stored globally. You can simply just

127.0.0.1:6379> set key value

However, GetSetDB does have separate storage spaces, once again, simply called “Databases”. Since GetSetDB is written in Go and Go is a language that doesn’t support classes, Spaces and Databases aren’t “objects”. They aren’t a grouped entity — instead, GetSetDB uses something called “executors”.

Executors are what parse and act upon the commands that are given and since there’s only two places we can send the commands to — the Space and different Databases — there are only two executors — the spaceExecutor and the databaseExecutor. Ever byte of information (or command) that is sent to the tcp server running at port 4998 passes through one of these executors.

Now how do we even send them commands? Since GetSetDB is just a tcp server program, we can use something like netcat or telnet to interact with it. They’re both usually pre-installed on Unix OSes. To connect to GetSetDB, make sure the server is running (as mentioned above) then open a new terminal and type —

$ nc localhost 4998
commands
new
del
list
rename
commands
version
datetime

If everything was installed and started correctly, you should see the following output after typing commands and hitting the enter key. Although GetSetDB does ship with a client, it’s not fully developed and you may encounter errors using it. An update will shortly be released to fix these.

Now you’re ready to order GetSetDB around using all its commands.

So let’s go through each of them.

Space Commands

As written in the diagram, the Space controls the CUD (Create, Update, and Destroy) functionality over GetSetDB’s database. That means that there are a few simple commands that you can use to create, rename and delete Databases. Let’s talk about all the commands now.

new

The first command that was implemented for the Space was new. And it does exactly what you might think it does — creates a new Database.

new database
new : `database`

You can enter whatever you’d like to be the name of Database in place of database. You can even create multiple Databases at once using just by placing a space in between names like so —

new users books authors
new : `users`, `books`, `authors`

A few things to keep in mind is that you can have as many Databases you want but each must have a unique name. GetSetDB throws an error if you try to create one with the same name of an old Database —

new users
error : database `users` already exists

Common convention dictates to have Database names in lowercase and only using alphanumeric characters. Even the inclusion of numbers isn’t preferred. But otherwise, all strings without a whitespace in between them are allowed.

del

Now we know about creating Databases with new; now meet del. It does the exact opposite of new and basically deletes the Database of which the name(s) were provided —

del users
del : `users`

You can delete multiple Databases as well —

del authors books
del : `authors`, `books`

If you try to delete a Database that doesn’t exist, you guessed it — GetSetDB throws an error —

del movies
error : database `movies` does not exist

list

Now you know how to create and delete Databases; now how do you view all of them? Simple, you use list. Create some dummy Databases to play around with —

new users authors books

Now to see all the Databases you have on your disk —

list
1 : authors
2 : books
3 : users

rename

We all make typos. What if you made one while creating a database and didn’t notice it until you had entered, say, a thousand entries into it. What do you do now? del and new it again? Nope, you rename it —

rename books novels
books : novel

Now for the errors. You need two arguments for the rename commands — the old database name and the new one. Once again, failure to provide either will result in an error.

rename novel
error : new name for database `novel` not provided

Now if you enter a database that doesn’t exist, you’ll get another error —

rename actors celebrities
error : database `actors` does not exist

commands

Even though GetSetDB is a lightweight database and there are a total of 14 commands in total, you can still sometimes forget what they are for the Space — even I do! So you can use commands to view all the commands you can use in a Space —

commands
new
del
list
rename
commands
version
datetime

version

Possibly the simplest command of them all, it simply returns the version of GetSetDB you have running on your computer —

version
1.0

datetime

This one was actually because I was learning about Go’s datetime package and I wanted to know the time a lot of the times I was using GetSetDB so datetime was implemented and it simply returns the date and the time of your local machine —

datetime
2019-01-07 01:49:57.295017818 +0530 IST m=+1912.511647078

Database Commands

Now, go back to the diagram. You now know how to interact with Space to control Databases… but how do you control the Databases? If you’ve ever used MySQL, there’s a simple way to “use” a database you’ve created and it’s just —

mysql> use Users;
Database changed
mysql>

And then any other command you execute will run on the database “Users” — GetSetDB is kind of similar to this. To run a command on any Database, we first type in the database name followed by the command. Like so —

authors <command>

Where <command>is the command you’ll enter. Now there are some restrictions to this — you can’t have a Database that has the name matching a Space command. Space commands are reserved names and that’s because the spaceExecutor executes Space commands only if it sees the first term (a command is composed of terms — a command is translated into an array of terms separated by a whitespace) belonging to the commandList — [new, del, list, rename, commands, version, datetime]. If you enter anything else as the first term, GetSetDB will treat it like the name of a Database and the following terms will be performed on the Database — now if this Database doesn’t exists, you’ll receive an error —

actors <command>
error : actors does not exist

Now that we know the syntax, let’s move to the commands themselves.

set

This is the first major command that’s similar to Redis — it sets a key to a particular value. It needs two arguments — a key and a value followed by it. The naming conventions for a key are the same as those for a Database — it’s good practice to use lowercase characters and there shouldn’t be any whitespace in the key. So to set a key to a value, you do this —

authors set dan brown
dan : brown

Remember how we have to explicitly specify the Database name we have to act upon? That’s what the authors is for — it just means that we’re set-ing the value of “brown” to the key “dan”.

One limitation of the set command is that you can only set ONE pair at a time in a command. Using a whitespace in between a value and set-ing it to a key works but internally, GetSetDB will store it as a different data-type — a list. That was kind of a lie — GetSetDB never actually stores anything other than plain text of the key with it’s value in this form —

key : value

You’ll see many occurrences of this syntax when using GetSetDB. Coming back to the point — datatypes. GetSetDB actually supports four different types of data — strings, numbers, uuids, and lists. The simplest way of differentiating them is as follows

A string is only a word with no whitespaces in it.

A number is any numeric value without any characters in it.

A UUID is any hexadecimal value that can match this regex —

\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b

And a list is any string that has whitespaces in it.

All of these are derived only if and when the user get-s them and that brings us to —

get

Once again, this command is inspired from Redis and is used to retrieve the value by providing a key to it —

authors get dan
string : brown

This is where you’ll see how GetSetDB infers and responds with the datatype of a value. Let’s set some more keys and see if GetSetDB gets it right —

authors set arthur conan doyle
arthur : conan doyle
authors set anonymous 84a96191-a496-43d4-aa7b-231645277211
anonymous : 84a96191-a496-43d4-aa7b-231645277211
authors set bond 007
bond : 007

I know they’re not all authors but for the sake of showcasing the different types of data GetSetDB supports, we get them —

authors get arthur
list : conan doyle
authors get anonymous
uuid : 84a96191-a496-43d4-aa7b-231645277211
authors get bond
number : 007

You see? GetSetDB inferred the types of data that was being provided to it and returns it as the key of the pair in the response with the actual value being the value.

del

Now that you know how to get and set keys, you will now know how to del-ete them —

authors del arthur
deleted : arthur

Nothing more to this. Just like with other Database commands, you can’t del-ete more than once pair at a time.

all

This command is just like the list Space command — it returns all the keys in the Database with a redundant index of them as the key of the response pair —

authors all
1 : dan
3 : anonymous
4 : bond

info

This command is useful for getting inf-ormation about your Database like it’s size in bytes and the path to its file where all the pairs are stores —

authors info
size : 62 bytes
path : /tmp/gsdb/authors.gsdb

count

If you need to know the number of keys you have in your data base, this command will count them for you using a fast and optimised line counter —

authors count
3

exists

This command exists (no pun intended) only for developers who want to write connectors for GetSetDB for different languages. GetSetDB is already designed in a way that if you enter the name of a Database as the first term, no terms that follow will be formulated into a command and only an error will be returned —

people exists
error : people does not exist

But if you were to use it with a Database that does actually exist, it’ll return a simple pair of exists : true.

authors exists
exists : true

And that is actually it, guys. That’s the entire database with all its commands. Of course, I didn’t really go into the implementation of everything or how the parser for GetSetDB nicknamed “Parrington” really works but this is all you need to know about GetSetDB to get up and running with it. Check out the repository here.

Manan

--

--

Manan

Computer Science and Mathematics enthusiast. I dabble in Philosophy.