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
Now before we get into typing commands or anything, let’s talk about how GetSetDB is structured. Take a look at this diagram —
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
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.
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.
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`
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 —
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.
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`
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 —
error : database `movies` does not exist
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 —
1 : authors
2 : books
3 : users
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?
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.
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
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 —
Possibly the simplest command of them all, it simply returns the version of GetSetDB you have running on your computer —
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 —
2019-01-07 01:49:57.295017818 +0530 IST m=+1912.511647078
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;
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 —
<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 —
error : actors does not exist
Now that we know the syntax, let’s move to the commands themselves.
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 —
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 —
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 doyleauthors set anonymous 84a96191-a496-43d4-aa7b-231645277211
anonymous : 84a96191-a496-43d4-aa7b-231645277211authors 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 doyleauthors get anonymous
uuid : 84a96191-a496-43d4-aa7b-231645277211authors 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.
Now that you know how to
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.
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 —
1 : dan
3 : anonymous
4 : bond
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 —
size : 62 bytes
path : /tmp/gsdb/authors.gsdb
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 —
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 —
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.
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.