Sedna LogoBackground Top
 
Home  |  Getting Started  |  Documentation  |  Demo  |  Download  |  Support 

1.3 Scheme API

Scheme API allows querying and managing XML data from an application written in Scheme. Scheme API follows the spirit of SchemeQL [10], an implementation of SQL 1992 for Scheme. The results of XQuery statements to the Sedna DBMS via the Scheme API can be represented either in XML or SXML [11].

1.3.1 Sessions

For working with the Sedna DBMS from Scheme, you should first establish a connection between the Scheme API driver and the Sedna DBMS. Here are two functions to manage connections:

> (sedna:connect-to-database host db-name user password)  
  : String String String String -> connection-object

Establishes a connection between the client application and the Sedna DBMS. Returns a ’connection’ object which encapsulate information about the connection. The arguments are strings that denote connection parameters:

  • host is the host where the Sedna DBMS is running. If it is on the same machine as your Scheme application, you can use "localhost" for the value of this parameter.
  • db-name is the name of the database you want to work with. You are to establish a separate connection for each database you would like to work with.
  • user is your user name for the session. You can use "SYSTEM" for the value of this parameter.
  • password is your password for the session. You can use the "MANAGER" value of this parameter.

To disconnect from the database, you can use the following function:

> (sedna:disconnect-from-database connection)  
  : connection-object -> void

Closes the connection represented by the connection object. If server fails to close the connection, the function closes the connection forcibly from the client side and raises the exception, as discussed in subsubsection 1.3.6.

1.3.2 Manage Transactions

After the connection with a database is established and the session is begun, you can run zero or more transactions in this session. Transactions are to be run sequentially, with no more than a single transaction at a time, so you should commit your running transaction before starting a new one.

To begin a new transaction, the following function is provided:

> (sedna:begin-transaction connection)  
  : connection-object -> void

It accepts the connection object (earlier created by sedna:connect-to-database function) and starts a new transaction. If the transaction could not be created, the exception is raised, as discussed in subsubsection 1.3.6.

To end your running transaction, you are provided with the following function:

> (sedna:end-transaction connection action)  
  : connection-object, symbol -> void

If action is ’COMMIT the transaction in the given connection will be committed, if ’ROLLBACK is given, the transaction will be rolled back.

1.3.3 Executing Queries and Updates

Within a transaction, you can execute zero or more queries to the database.

> (sedna:execute-query connection query)  
  : connection-object, string -> result

The first argument is the connection object, earlier created by sedna:connect-to-database function. The query is represented as a string and can express one of the following kinds of statements:

  • XQuery statement – for querying data from the database, without modifying it;
  • Update statement – for making modifications to the database you work with;
  • Bulk load command – for loading a new XML document from the local file to the database;
  • Database management statement – to create index, trigger, retrieve metadata, etc.

If an error occurs at the server side during query execution (e.g. the requested document not found), the function raises an exception that contains the message about the error occurred.

In the successful case of query execution, sedna:execute-query returns #t for the last 3 kinds of queries, to denote a successful update made to the database. The XQuery query results to a sequence of items, which are evaluated lazily and are represented as a pair:

xquery-result ::= (cons current-item promise)

This way of result representation is very close to the notion of SchemeQL cursor [10] (with the only difference in that the Scheme API driver returns XQuery items instead of table rows returned by SchemeQL). The first member of the pair is the current-item represented in SXML, and the second member of the pair holds a promise (which can be forced) to evaluate and return the next item in the result sequence.

To iterate over the result sequence, you can use the function:

> (sedna:next xquery-result)  
  : xquery-result -> xquery-result or ’()

which forces the evaluation of the following items in the result sequence, until the end of the sequence is reached.

Such design allows you to process a query result in a lazy stream-wise fashion and provides you with an ability to process large query results, which would not otherwise fit in the main memory.

However, for query results that are not very large, you may find it convenient to evaluate them all at once and represent the result sequence as a Scheme list. Scheme API provides a function that converts the xquery-result into the list that contains all items of the result sequence:

> (sedna:result->list xquery-result)  
  : xquery-result -> (listof item)

To obtain the result sequence in the form of the list, you can execute your queries as a superposition of the above considered functions:

(sedna:result->list  
  (sedna:execute-query connection query))

It should be noted that the XQuery statement result in that case exactly corresponds to the term of a node-set in the XPath implementation in Scheme SXPath [14].

If you want to obtain your query results in XML instead of SXML, you can use the function:

> (sedna:execute-query-xml connection query)  
  : connection-object, string -> result

It is the counterpart of earlier discussed sedna:execute-query and has the same signature, but represents query results in XML. The function returns a sequence of items, in the form of xquery-result discussed above, but the current-item is now a string containing the representation for the current item in the form of XML.

1.3.4 Bulk Load from Stream

The following wrapper function provides a natural way to load an input stream containing an XML document into your database:

> (sedna:bulk-load-from-xml-stream  
      connection port document-name . collection-name)  
  : connection-object, input-port,  
      string [, collection-name] -> boolean

As for sedna:execute-query, the first argument here is the connection object, earlier created by sedna:connect-to-database function. Argument port is a Scheme input port and is supposed to contain a well-formed XML document. Argument document-name specifies the name that will be given to the XML document within a database. If the 4-th argument collection-name is supplied, the XML document is loaded into the collection which name is specified by the collection-name argument. If the 4-th argument of the function call is not supplied, the XML document is loaded into the database as a standalone document.

By allowing you to specify the input port you would like to use, this function provides a higher-level shortcut for sedna:execute-query when bulk load from stream is concerned. For more details on bulk load, see section 2.4.

1.3.5 Higher-level Function for a Transaction

This higher-level function provides a convenient way for executing a transaction consisting of several queries, within a single function call:

> (sedna:transaction connection . queries)  
  : connection-object, string* -> result

This function starts a new transaction on the connection objects and executes all the queries given in order. If no exception occurs, the function commits the transaction and returns the result of the last query. If any exception occurred during query execution, the function sends rollback to the Sedna DBMS and passes along the exception to the application.

1.3.6 Error handling

Error handling in the Scheme API driver is based on the exception mechanism suggested in the (currently withdrawn) SRFI-12 [12]. The SRFI-12 exception mechanism is natively supported in the Chicken Scheme compiler [13]. In the Scheme API driver, we also provide the SRFI-12 implementation for PLT and Gambit.

1.3.7 Code Example

This section presents an example that illustrates the application of the Scheme API driver.

; Load the necessary Scheme API driver files  
(load "collect-sedna-plt.scm")  
 
; Create a connection  
(define conn  
  (sedna:connect-to-database "localhost" "testdb"  
                             "SYSTEM" "MANAGER"))  
; Begin a transaction  
(sedna:begin-transaction conn)  
 
; Bulk load  
(call/cc  
 (lambda (k)  
   (with-exception-handler  ; Exception handler  
    (lambda (x)  
      (display "File already loaded to the database")  
      (newline)  
      (k #f))  
    (lambda ()  
      (sedna:execute-query conn  
                           "LOAD ’region.xml’ ’regions’")))))  
 
; Execute a statement and represent it as an SXML nodeset  
(pp  
 (sedna:result->list  
  (sedna:execute-query conn "doc(’region’)/*/*")))  
 
; Update statement  
(pp  
 (sedna:execute-query conn  
                  "UPDATE delete doc(’region’)//africa"))  
 
; Querying all regions once again  
(pp  
 (sedna:result->list  
  (sedna:execute-query conn "doc(’region’)/*/*")))  
 
; Commit transaction  
(sedna:end-transaction conn ’COMMIT)  
 
; Close the connection  
(sedna:disconnect-from-database conn)

You can find the full version of this example and the Scheme API driver code in:

[win:] INSTALL_DIR\examples\api\scheme  
[nix:] INSTALL_DIR/examples/api/scheme

where INSTALL_DIR refers to the directory where Sedna is installed.

Before running the example make sure that the Sedna DBMS is installed and do the following steps:

  1. Start Sedna by running the following command in a command line:
    se_gov

    If Sedna is started successfully it prints ”GOVERNOR has been started in the background mode”.

  2. Create a new database testdb by running the following command:
    se_cdb testdb

    If the database is created successfully it prints ”The database ’testdb’ has been created successfully”.

  3. Start the testdb database by running the following command:
    se_sm testdb

    If the database is started successfully it prints ”SM has been started in the background mode”.

If the Sedna DBMS is running on the same computer as your Scheme application, you don’t need to change anything in the example code. If the Sedna DBMS is running on a remote machine, you should use the name of this machine when connecting to the database with sedna:connect-to-database function.

For running the example supplied, you should copy all files from the folder:

     [win:] INSTALL_DIR\examples\api\scheme  
     [nix:] INSTALL_DIR/examples/api/scheme

into the folder where the Scheme API driver code is located

     [win:] INSTALL_DIR\driver\scheme  
     [nix:] INSTALL_DIR/driver/scheme

where INSTALL_DIR refers to the directory where Sedna is installed.

You can use PLT DrScheme GUI to open and run "client.scm" in the graphical mode. You can also run the example from your command line, by typing:

mzscheme -gr client.scm

For running the example with a different Scheme implementation (Chicken or Gambit), uncomment the corresponding line at the beginning of the example code in "client.scm" and follow the instructions of the chosen Scheme implementation in running the program.