Frequently Asked Questions
General questions
Building, modifying, and understanding librta
General questions
What is librta?
Librta is library that lets PostgreSQL clients talk to your daemon
using SQL. It is not a stand-alone database server but a library
which presents your program's internal structures and arrays as
if they were database tables. Your program needs to open a socket
to allow the clients to connect and you have to fill in two librta
data structure to tell librta about the tables and columns you
want to make visible as Postgres tables.
What is the purpose of librta?
It provides a means for external programs to view and edit the
tables in your running program. This makes debugging easier and
means that the user interface parts of your system can be kept
apart from the core functionality.
So, is this a database, or what?
No, it is not a database. It is an API which lets external
programs view and edit your program's internal data as if the
data were in a database.
Is this like the /proc filesystem?
Yes, in a way. The /proc system lets you view the kernel's internal
data as if the data were stored in files in a filesystem. Librta
lets you view your program's internal tables (linked lists or arrays
of structures) as if they were tables in a PostgreSQL database.
Why PostgreSQL?
Mostly because both the design and the documentation of the
PostgreSQL protocol are very clean and well done. PostgreSQL offers
a simple, well documented protocol to the client. (BTW: Our thanks
to the designers and tech-writers for PostgreSQL.)
What SQL commands are implemented?
Only four: SELECT, UPDATE, INSERT, and DELETE, and even these are
only a subset of their PostgreSQL equivalents. See rta.h for the
syntax details of the commands. While librta does not implement
transactions, we've found that in practice most commands are self
contained and transactions are not needed.
What SQL/Postgres commands are not
implemented?
Since this is not a database, it does not need the usual PostgreSQL
meta tables, nor does it need CREATE TABLE, ALTER TABLE, or DROP
TABLE.
The command line tool for PostgreSQL, psql, will connect to
a program with librta, but none of the psql backslash commands
will work (since most of the backslash commands require a real
PostgreSQL database).
Why such a small subset of SQL?
Since this is not a database and just an API to your data, only
SELECT and UPDATE are not really necessary.
Who should not use librta?
Librta is great if you have data already arranged as structs or as
array of structs. It is a little more difficult to use if you have
lots of structs pointing to other structs pointing to other
structs. That is, it is a good fit for simple tables of data and is
not a good fit for a deeply nested tree structure with different
structure definitions at each branch.
How big is it?
The stripped shared-object SQL interface library (librtadb.so.3)
is 56 KB and the static (.a) library is 50 KB. On NuttX on an
ARM M3 the library size is about 35 KB.
Do I need to know SQL to use librta?
Not really. Usually only two commands are required and they match
pretty well with the intuitive idea of "change this column in this
table where ...". It is pretty simple.
How difficult is it to learn and use librta?
It is easy to learn. There are only two important data structures
(one to describe a table and one to describe a column) and only seven
subroutines in the API. The tutorial elsewhere on this page should
give you a pretty good idea of the simplicity of the approach.
It is simple but *may* require some effort on your part. Each table
and each column in each table needs to be defined in a data
structure. While simple, it can be a fair amount of work.
Does it work with linked lists and B-trees?
Yes, it works with linked lists and B-trees. Table definitions
include an optional iterator routine which steps from
one row to the next. If your program can step from one element
to the next you can define an iterator for it. See the API
spec for more details on iterators.
How do I report bugs?
Please select "Contact Info" from the menu above to open a
query form. Please give as much detail as possible.
Where can I get help?
Please select "Contact Info" from the menu above to open a
query form. Please give as much detail as possible.
Do you need/take donations?
Please send bug reports and change requests. Send money to the Free
Software Foundation.
Does hurt or help security?
It depends. Your application can be very secure using using Unix
sockets that are owned by root and have 0600 permissions. Forcing
the data into an SQL form may help prevent some kinds of attacks.
On the other hand, using TCP sockets makes debugging much easier
and makes it easy to work with web-sockets and some other types
of web technology.
Building, modifying, and understanding librta
What do I need to do to use librta in my
program?
You need to describe each table you wish to make available. A
typical table might be an array of structures. Each member of
the structure forms a column of the table and each instance of
the structure is a row. You need to describe the table by
giving the attributes of the table in general and a description
of each column in the table. See the sample application and
the API reference for more detail.
What tools are available to explore librta
tables?
Librta uses two internal tables (rta_tables and rta_columns) to
store information about all of the tables visible to librta. It
includes a "table editor" written in PHP that lets you use a web
browser to view and edit any table in your application. The librta
table editor does not need prior knowledge about the tables since
it can read everything it needs from the two meta tables. Follow
the "Live Demo" link to see the table editor in action.
What libraries, tools and include files are
needed?
We use the following system include files: libgen.h, limits.h,
stdarg.h, stddef.h, stdio.h, stdlib.h, string.h, syslog.h, and the
following system and utility calls: closelog(), dirname(),
fclose(), fdopen(), fgets(), fopen(), fprintf(), free(), malloc(),
memchr(), mkstemp(), offsetof(), openlog(), rename(), snprintf(),
sprintf(), sscanf(), strcat(), strcmp(), strcpy(), strlen(),
strncmp(), strncpy(), strstr(), syslog(), va_arg(), va_end(),
va_start(). You will need yacc (bison) and lex (flex) to build
librta.
Do I need the Postgres libraries?
Your daemon application does not need any libraries or include
files from the PostgreSQL distribution, but your client
applications probably will.
Can I link to it statically?
Yes, You can link to the .a file or just include the .c files in
the build of your application.
What has it been tested on?
It has been used successfully on Red Hat, SUSE, and Ubuntu
systems. Builds are also available for FreeBSD, Macintosh
and Windows. It also works on NuttX although there is no package
for it.
Can I add my own data type?
Sure! You will need to modify the lex program to recognize the
new data type as well as the .c files which print or compare its
values.
Why are there "magic" numbers in the
code?
Several places in the code contain what seem like magic values.
These are all related to the PostgreSQL protocol and should all be
described by comments in the surrounding code.
Why are the pseudo-tables arrays of pointers?
The short answer is to save memory. If rta_add_table() were to copy
the table definition your application would have the definition two
places in memory: internal to librta, and in your application code.
By saving the pointers to the table and column definitions we avoid
using lots of memory to duplicate data. Saving pointers has the
second advantage of letting you change the table definition on the
fly if needed.
Why do I get segmentation violations?
We've tried very hard to eliminate memory leaks and segmentation
violations from the librta package but some might have slipped
through. A common source of problems is overrunning a string. Be
sure to verify that your strings have the proper size specified in
the column definitions.
How can I change the size of a table?
Allocate enough memory to store the new, larger table. Copy the old
table into the new space. Initialize the new rows added. Copy the
address of the new table into the "address" field of the table
definition and update the "nrows" field with the new number of
rows.
Why use native data type instead of INT4
and INT8?
The idea is to give easy access to *your* data structures. Since
most programmers use the native int, long long, and float, we do
too.
Why do I get "error while loading shared libraries:
librtadb.so.3"?
You need to put the librtadb.so files into one of
the system library directories or you need to something like "export
LD_LIBRARY_PATH=../src" in order to let the application find the
library.
How big should I make the output buffer for
rta_dbcommand()?
It depends on the number of rows and the size and number of fields
you request. You should be able to estimate the number of
characters in your response. Assume that strings are returned with
all bytes filled, that integers return 12 characters per field,
longs return 24, and floats return 24. Thus if you request two
integers, a 40 byte string and a float, you would need about
40+(2*12)+24=88 bytes. The Postgres overhead per row returned is
about 4 bytes. Make the output buffer for rta_dbcommand() big enough to
hold the maximum number of rows you want times the size of each
row. Be sure to use LIMIT and OFFSET to step through a big list of
returned rows.
Can I export a simple variable?
Sure. Just define a single column for your variable and a table
with a single row. Simple variables, single structures, linked
lists, or arrays of structures are all easy to make visible as
tables.
Is librta thread safe?
Librta is not currently thread safe. Please contact the authors
if this is very high on your wish list.
What is in the To-Do list?
Please let the authors know what features you would like added
or removed from Run Time Access. No additional changes are
anticipated at this time, but the list of possible changes
includes:
- Update to the latest PostgreSQL protocol
- UTF-8 support
- printf format string in the column definition
- ability to register more than one trigger per column
- secure login maintaining Postgres compatibility
- Add support in shared memory by adding locking
- specify pre or post for the write callback
- count(*) function
- add a column data type of "table" to allow nested tables
- make it thread safe