On this page:
3.1 Defining persistent structure types
define-persistent-struct
3.2 IDs and revisions
struct-id
set-struct-id!
struct-revision
set-struct-revision!
struct-saved?
Version: 4.1.3.3

3 Persistent structures

Entities, relationships and attributes

A persistent structure is a PLT structure that Snooze can save to a database. Snooze attaches entity metadata to each persistent struct type via a property called prop:entity. The metadata serves two purposes:

A persistent structure type with n fields is mapped to a database table with n+2 columns: an integer id which acts as a primary key for table, an integer revision number which helps prevent against concurrent writes in multi-threaded applications, and a column for each attribute in the type definition. ids and revisions are automatically allocated by Snooze and should not normally be updated by application code: the lifecycle of these fields is described in Saving and deleting structures.

3.1 Defining persistent structure types

(define-persistent-struct id (attr-defn ...+) entity-option ...)
 
attr-defn = [attr-id type attribute-option ...]
     
attr-option = #:column-name symbol?
     
entity-option = #:table-name symbol?
  | #:on-save (listof (connection? persistent-struct? -> persistent-struct?))
  | #:on-insert (listof (connection? persistent-struct? -> persistent-struct?))
  | #:on-update (listof (connection? persistent-struct? -> persistent-struct?))
  | #:on-delete (listof (connection? persistent-struct? -> persistent-struct?))
  | #:property struct-type-property? any

Creates a new persistent structure, and binds variables related to the new structure type. A define-persistent-struct with n attributes defines the following identifiers:

By default, persistent structures are stored in rows in a database table of the same name. The #:table-name entity option allows you to override the default table name and provide something more user-friendly: hyphen characters in table names must be escaped in most DBMSs. Similarly, the #:column-name attribute option allows you to override the default column name for each attribute. The column names for id and revision may not be changed.

(part "pipelines")

The #:on-save, #:on-insert, #:on-update and #:on-delete keywords allow you to specify database pipelines to be run during calls to save! and delete!.

Persistent structures are completely inspectable. ids and revisions are visible in their printed forms and are exposed by the struct form from scheme/match. For example:

  ; person : (persistent-struct (U string #f) (U integer #f))
  > (define-persistent-struct person
      ([name type:string]
       [age  type:integer]))
  ; dave : person
  > (define dave
      (make-person "Dave" 30))
  ; Print dave: id and revision shown:
  > dave

  #(struct:person #f #f "Dave" 30)

  ; Match against dave: no id and revision:
  > (match dave
      [(struct person (id revision name age))
       (list id revision name age)])

  (#f #f "Dave" 30)

Persistent structure types are not meant to be subtyped, although this feature is planned for a future version of Snooze.

3.2 IDs and revisions

Every persistent struct has an ID and a revision. The ID acts as a primary key in the database, and the revision helps protect against concurrent database updates.

(struct-id struct)  (U integer? #f)
  struct : persistent-struct?

Returns the ID of struct, or #f if struct is not saved in the database.

Warning: Use struct-saved? rather than struct-id to check whether or not a struct has been saved to the database. Changes in later versions of Snooze may affect whether struct-id returns #f for unsaved structs.

(set-struct-id! struct id)  void?
  struct : persistent-struct?
  id : (U integer? #f)

Sets the id of struct. You should not normally have to use this procedure: Snooze does this automatically when you save or delete a struct.

(struct-revision struct)  (U integer? #f)
  struct : persistent-struct?

Returns the last revision number of struct, or #f if struct is not saved in the database.

The revision number is set to 0 when a structure is first saved and is incremented on each subsequent save. Snooze raises exn:fail:snooze:revision if a structure has an incompatible revision number when you try to save it. This protects against common concurrency problems.

(set-struct-revision! struct rev)  void?
  struct : persistent-struct?
  rev : (U integer? #f)

Sets the revision number of struct to rev. You should not normally have to use this procedure: Snooze does this automatically when you save or delete a struct.

(struct-saved? struct)  boolean?
  struct : persistent-struct?

Returns #t if struct has been saved to the database and #f if it has not.