1 Quick start
Thank you for trying Snooze. Read on to find out how you can get everything up and running on your system. If you have any questions please don’t hesisitate to contact us; our email addresses are at the beginning of this manual.
We hope you enjoy Snooze!
– Untyped
1.1 Install a DBMS
The first thing you’ll need to do is download and install a DBMS. Snooze currently supports two database backends: SQLite 3.6x and PostgreSQL 8.3x. Get hold of one of these, install it, configure it, and set up a blank database:
if you are using SQLite, creating a database is as simple as creating a file somewhere on your local filesystem;
if you are using PostgreSQL your will need to create a user with the necessary privileges and set up your "pg_hba.conf" to allow TCP/IP connections from localhost.
This is probably the hardest part of the setup process, and unfortunately it falls outside the scope of this document. If you are looking for a quick-and-easy setup for your system, you might want to follow the installation instructions for your platform on the SQLite web site.
1.2 Link the Snooze API
Once have chosen your DBMS platform, you will need to create a Snooze interface in Scheme. This involves creating two scheme/class objects: one contains database-independent code, the other contains code specific to your database.
Create a blank file in your project directory called "db.ss" and enter the following template code:
|
(planet untyped/snooze/<<DB>>/<<DB>>)) |
|
(define-snooze-interface |
(make-snooze (make-database ; TODO: arguments...))) |
|
(provide (all-from-out (planet untyped/snooze/snooze)) |
(snooze-interface-out)) |
Change <<DB>> to postgresql8 or sqlite3 depending on your choice of DBMS.
define-snooze-interface is an unhygeinic macro that takes a snooze object as an argument and defines wrapper procedures for each of its important methods. snooze-interface-out provides those procedures to the rest of your application. All of the procedures and macros described in the rest of this manual are provided by define-snooze-interface or directly from "snooze.ss".
All you need to do to complete "db.ss" is fill in the arguments to make-database. The arguments will be different depending on whether you are using SQLite or PostgreSQL:
if you are using SQLite, rewrite the call to make-database like this:
(make-database "<<FILENAME>>")
where <<FILENAME>> is the path to your database file;
if you are using PostgreSQL, rewrite the call to make-database like this:
(make-database #:server "<<SERVER>>"
#:port <<PORT>>
#:database "<<DATABASE>>"
#:username "<<USERNAME>>"
#:password "<<PASSWORD>>")
where:
<<SERVER>> is the hostname of your database server (e.g. localhost);
<<PORT>> is the port number to connect on (usually 5432; note that this is an integer - not a string);
<<DATABASE>> the name of the relevant database on your server;
<<USERNAME>> is the username you want to connect with;
<<PASSWORD>> is the password for this username (this is an optional argument).
Note: the PostgreSQL version of make-database has additional keyword arguments to configure SSL if you need it.
1.3 Start using Snooze
Now you are ready to connect to a database and start storing data. Create a new module called "test.ss" in the same directory as "db.ss". Edit this new module and enter the following test script:
|
(require "db.ss") |
|
; Define a datatype that we can save to the database: |
(define-persistent-struct person |
([name type:string] |
[age type:integer] |
[gender type:symbol])) |
|
; Define aliases of person and its attributes. |
; These aliases are used in queries: |
; - person1 |
; - person1-id |
; - person1-revision |
; - person1-name |
; - person1-age |
; - person1-gender |
(define-alias person1 person) |
|
; Print the people that are saved in the database: |
(define (print-people) |
(define people (find-all (sql (select #:from person1)))) |
(printf "People in the database:~n") |
(printf " NONE~n") |
(for ([person people]) |
(printf " ~s~n" person)))) |
|
; Create some people (in memory): |
(define-values (alice bob charlie) |
(values (make-person "Alice" 20 'F) |
(make-person "Bob" 25 'M) |
(make-person "Charlie" 30 'F))) |
|
; Connect to the database: |
(call-with-connection |
(lambda () |
|
; Create a database table to house person data: |
(create-table person) |
|
; There aren't any people saved yet: |
(print-people) |
|
(save! alice) |
(save! bob) |
(save! charlie) |
|
; Now they're in the database: |
(print-people) |
|
(delete! alice) |
(delete! bob) |
(delete! charlie) |
|
; And now they're gone again: |
(print-people) |
|
; Okay, we're done. Drop the table: |
(drop-table person))) |
Run the code with the following command line:
mzscheme test.ss
You should see the following output:
People in the database: |
NONE |
People in the database: |
#(struct:person "Alice" 20 'F) |
#(struct:person "Bob" 25 'M) |
#(struct:person "Charlie" 30 'F) |
People in the database: |
NONE |
Several bits of code Snooze functionality are demonstrated in this example. Click on the names below to see the definitions of the relevant procedures:
define-persistent-struct is a macro that defines a structure type that can be saved to the database: the type specifiers give Snooze hints about how to serialize and deserialize field values;
call-with-connection sets up a default connection that is used by many Snooze API calls: the connection is established and terminated as control enters and leaves the argument thunk via continuation jumps or the natural flow of the program;
find-all and q:select are part of the Snooze query mechanism (which has most of the expressiveness of full SQL);
create-table and drop-table are used to issue the corresponding CREATE TABLE and DROP TBALE commands to the database;
save! is used to save a persistent struct to the database and delete! is used to delete it again.
That completes this quick start guide. In "db.ss" you now have everything you need to start defining your own persistent struct types and saving structs to your database. The remainder of this manual serves a reference for the various parts of Snooze.