1.2 C API
libsedna is the C application programmer’s interface to Sedna XML DBMS. libsedna is
a set of library functions that allow client programs to access one or more databases of
Sedna XML DBMS and manipulate database data using database language (XQuery
and XUpdate) described in Section 2.
libsedna library is supplied with two header files: "libsedna.h", "sp_defs.h".
Client programs that use libsedna must include the header file libsedna.h, must link
with the libsedna library and provide the compiler with the path to the directory where
"libsedna.h", sp_defs.h files are stored.
For convenience three versions of libsedna are provided on the Windows operating
system:
- libsednamt.lib - static multi-threaded version built with /MT option. Use
it if you compile your project with /MT[d] option.
- libsednamd.lib - static multi-threaded version built with /MD option. Use
it if you compile your project with /MD[d] option.
- sednamt.dll - dynamic version. sednamt.lib is import library.
On Unix-like operating systems the following versions of libsedna are
provided:
- libsedna.so - dynamic shared library.
- libsedna.a - static version of the library.
- libsedna_pic.a - static version of the library with PIC enabled. You may
need it to build drivers for Sedna which are based on libsedna.
1.2.1 Errors Handling
C API provides set of functions for sessions and transactions management, query and
update statements execution, etc. If the function fails it returns negative value. In this
case application can obtain the error message and code which help to understand the
reason of the error occurred.
To get the last error message use SEgetLastErrorMsg function:
char* SEgetLastErrorMsg(SednaConnection* conn)
Parameters:
- conn - a pointer to an instance of the SednaConnection type (see 1.2.2,
Connecting to a Database section for details on how to obtain a connection
instance).
The function SEgetLastErrorCode returns the last error code occurred in the
session:
int SEgetLastErrorCode(struct SednaConnection *conn)
Parameters:
- conn - a pointer to an instance of the SednaConnection type (see 1.2.2,
Connecting to a Database section for details on how to obtain a connection
instance).
1.2.2 Connecting to a Database
Before working with Sedna an application has to declare variable of the SednaConnection
type and initialize it in the following manner:
struct SednaConnection conn = SEDNA_CONNECTION_INITIALIZER;
Note 1 The initialization with SEDNA_CONNECTION_INITIALIZER is mandatory
for Sedna version 0.5 and earlier.
To start working with Sedna an application has to open a session via establishing an
authenticated connection with the server using SEconnect:
int SEconnect(SednaConnection* conn,
const char* url,
const char* db_name,
const char* login,
const char* password)
Parameters:
- conn - is a pointer to an instance of SednaConnection type, that is associated
with a session. The instance of SednaConnection type is initialized by the
SEconnect if the session is open successfully.
- url - the name of the computer where the Sedna DBMS is running. This
parameter may contain a port number. If the port number is not specified,
the default port number (5050) is used.
- db_name - the name of the database to connect to.
- login - user login.
- password - user password.
Return values:
If the function succeeds, the return value is positive:
- SEDNA_SESSION_OPEN - connection to the database is established,
authentication passed successfully.
If the function fails, the return value is negative and session is not opened:
- SEDNA_AUTHENTICATION_FAILED - authentication failed.
- SEDNA_OPEN_SESSION_FAILED - failed to open session.
- SEDNA_ERROR - some error occurred.
To access multiple databases at one time or to better process its complex logic an
application can have several sessions open at one time.
When an application finished it’s work with the database, it must close the session.
SEclose finishes the session and closes the connection to the server. SEclose also frees
resources that were equipped by the call to SEconnect function, that is for every
successful call to SEconnect there must be a call to SEclose in the client program. You
must call SEclose both when application finishes its work with the database,
and when application cannot work with the database anymore due to some
error.
int SEclose(SednaConnection* conn)
Parameters:
- conn - a pointer to an instance of the SednaConnection type, associated with
a session to be closed.
Return values:
If the function succeeds, the return value is positive:
- SEDNA_SESSION_CLOSED - session closed successfully.
If the function fails, the return value is negative:
- SEDNA_CLOSE_SESSION_FAILED - session closed with errors.
- SEDNA_ERROR - some error occurred.
1.2.3 Setting Session Options
An application can set attributes that govern aspects of a session using
SEsetConnectionAttr:
int SEsetConnectionAttr(struct SednaConnection *conn,
enum SEattr attr,
const void* attrValue,
int attrValueLength)
Parameters:
- conn - a pointer to an instance of the SednaConnection type, associated with
a session to be closed.
- attr - an attribute to set (one of the predefined Sedna connection attributes
listed below).
- attrValue - a pointer to the value to be associated with the attribute.
- attrValueLength - a length of the value in bytes.
Return values:
If the function succeeds, the return value is positive:
- SEDNA_SET_ATTRIBUTE_SUCCEEDED - the attribute was set successfully.
If the function fails, the return value is negative:
- SEDNA_ERROR - some error occurred.
Supported attributes:
- SEDNA_ATTR_AUTOCOMMIT Autocommit mode is the default transaction
management mode of the Sedna server (SEDNA_AUTOCOMMIT_OFF is the
default value of this attribute). Every XQuery or update statement is
committed or rolled back when it completes. If a statement completes
successfully, it is committed; if it encounters any error, it is rolled back. A
connection to an instance of the Sedna database operates in autocommit
mode whenever this default mode has not been overridden by setting this
attribute into SEDNA_AUTOCOMMIT_OFF value.
|
| Atrribute values | Value size |
|
| SEDNA_ATTR_AUTOCOMMIT_ON, | |
SEDNA_ATTR_AUTOCOMMIT_OFF | sizeof(int) |
|
| |
- SEDNA_ATTR_SESSION_DIRECTORY connection attribute defines the
session directory. If this attribute is set, paths in the LOAD statement 2.4 or
LOAD MODULE are evaluated relative to the session directory.
|
| Atrribute values | Size of value |
|
| path to directory | length of path |
|
| |
- SEDNA_ATTR_DEBUG connection attribute turns on/off query debug mode. Query
debug mode is off by default. Note: SEDNA_ATTR_DEBUG connection attribute
must be set only after SEconnect has been called on the conn.
|
| Atrribute values | Value size |
|
| SEDNA_ATTR_DEBUG_ON, | |
SEDNA_ATTR_DEBUG_OFF | sizeof(int) |
|
| |
- SEDNA_ATTR_CONCURRENCY_TYPE connection attribute changes the
mode of the next transactions. Transaction can be set to run as
READ-ONLY (SEDNA_READONLY_TRANSACTION) or UPDATE-transaction
(SEDNA_UPDATE_TRANSACTION). READ-ONLY transactions have one major benefit:
they never wait for other transactions (they do not have to acquire any
document/collection locks). However they might access slightly obsolete state of
the database (for example, they probably would not see the most recent
committed updates). You should use READ-ONLY transactions in a highly
concurrent environment. Notice that the current transaction, if any, will be
forcefully committed.
|
| Atrribute values | Value size |
|
| SEDNA_READONLY_TRANSACTION, | |
SEDNA_UPDATE_TRANSACTION | sizeof(int) |
|
| |
- SEDNA_ATTR_QUERY_EXEC_TIMEOUT connection attribute allows to set the limit on
query execution time. If set, for each next query in this session, query execution
will be stopped if it lasts longer than timeout set. In this case transaction in
bounds of which the query run is rollback. By default (value 0) there is no any
timeout for query execution, that is a query can be executed as long as
needed.
|
| Atrribute values | Value size |
|
| time in seconds | sizeof(int) |
|
| |
- SEDNA_ATTR_MAX_RESULT_SIZE connection attribute allows to set the
limit on query result size. If this attribute is set, the server will cut the
result data if its size exceeds the specified limit. By default, result data
that is passed from server in response to user query can be of unlimited
size.
|
| Atrribute values | Value size |
|
| size in bytes | sizeof(int) |
|
| |
- SEDNA_LOG_AMOUNT connection attribute changes the mode of logical logging for
the following transactions in the same session. Transaction can be set to run in
full log mode (SEDNA_LOG_FULL) or reduced log mode (SEDNA_LOG_LESS). The
former means transaction writes much less log info during bulk loads.
Also, when such transaction commits the checkpoint is made, which
might greatly reduce recovery time. There is a caveat, however: such
transaction always runs in exclusive mode, which means there can be no
concurrent transactions. Before it starts it waits for other concurrent
transactions to finish. In turn, all other transactions will not start until exlusive
transaction finishes. You should use this option with care, since it effectively
stalls any concurrent activity. The main purpose of such transactions
is to bulk-load data. The other possible use-case includes transactions
performing heavy update operations. Since checkpoint will be made when such
transaction commits, it might reduce recovery time in case of database
crash. Otherwise, you should not use this option since you will not gain
anything. Notice also that the current transaction in the same session, if
any, will be forcefully committed. The default value for this attribute is
SEDNA_LOG_FULL.
|
| Atrribute values | Value size |
|
| SEDNA_LOG_LESS, | |
SEDNA_LOG_FULL | sizeof(int) |
|
| |
An application can retrieve current value of hte connection attributes using
SEgetConnectionAttr:
int SEgetConnectionAttr(struct SednaConnection *conn,
enum SEattr attr,
void* attrValue,
int* attrValueLength);
Parameters:
- conn - a pointer to an instance of the SednaConnection type, associated
with a session to be closed.
- attr - an attribute to retrieve.
- attrValue - a pointer to memory in which to return the current value of
the attribute specified by attr.
- attrValueLength - a length of the retrieved value in bytes.
Return values:
If the function succeeds, the return value is positive:
- SEDNA_GET_ATTRIBUTE_SUCCEEDED - the attribute was retrieved successfully.
If the function fails, the return value is negative:
- SEDNA_ERROR - some error occurred.
To reset all connection attributes to default values use:
int SEresetAllConnectionAttr(struct SednaConnection *conn);
Parameters:
- conn - a pointer to an instance of the SednaConnection type, associated
with a session to be closed.
Return values:
If the function succeeds, the return value is positive:
- SEDNA_RESET_ATTRIBUTES_SUCCEEDED - attributes has been reset
successfully.
If the function fails, the return value is negative:
- SEDNA_ERROR - some error occurred.
1.2.4 Transactions Management
An application can execute queries and updates against the specified database only in
the scope of a transaction. That is, once a session has been opened, an application can
begin a transaction, execute statements and commit this transaction. In a session
transactions are processed sequentially. That is, application must commit an ongoing
transaction before beginning a new one.
There are two ways to manage transactions in Sedna sessions: autocommit mode and
manual-commit mode:
- Autocommit mode. Each individual statement is committed when it
completes successfully. When running in autocommit mode no other
transaction management functions are needed. By default, Sedna sessions
are run in autocommit mode.
- Manual-commit mode. Transaction boundaries are specified explicitly
by means of SEbegin, SEcommit and SErollback functions. All statements
between the call to SEbegin and SEcommit/SErollback are included in the
same transaction.
An application can switch between the two modes using SEsetConnectionAttr
and SEgetConnectionAttr functions (see 1.2.3) for SEDNA_ATTR_AUTOCOMMIT
attribute.
To specify transaction boundaries application uses SEbegin, SEcommit and
SErollback functions. SEbegin function starts new transaction in the provided
session:
int SEbegin(SednaConnection* conn)
Parameters:
- conn - a pointer to an instance of the SednaConnection type.
Return values:
If the function succeeds, the return value is positive:
- SEDNA_BEGIN_TRANSACTION_SUCCEEDED - transaction has been successfully
started.
If the function fails, the return value is negative:
- SEDNA_BEGIN_TRANSACTION_FAILED - failed to start a transaction.
- SEDNA_ERROR - some error occurred.
SEcommit function commits the current transaction:
int SEcommit(SednaConnection* conn)
Parameters:
- conn - a pointer to an instance of the SednaConnection type.
Return values:
If the function succeeds, the return value is positive:
- SEDNA_COMMIT_TRANSACTION_SUCCEEDED - transaction has been committed.
If the function fails, the return value is negative:
- SEDNA_COMMIT_TRANSACTION_FAILED - failed to commit transaction.
- SEDNA_ERROR - some error occurred.
SErollback function rollbacks the current transaction:
int SErollback(SednaCommection* conn)
Parameters:
- conn - a pointer to an instance of the SednaConnection type.
Return values:
If the function succeeds, the return value is positive:
- SEDNA_ROLLBACK_TRANSACTION_SUCCEEDED - transaction has been
rollbacked.
If the function fails, the return value is negative:
- SEDNA_ROLLBACK_TRANSACTION_FAILED - failed to rollback transaction.
- SEDNA_ERROR - some error occurred.
1.2.5 Getting Connection and Transaction Status
An application can obtain the connection status by SEconnectionStatus function:
int SEconnectionStatus(SednaConnection* conn)
Parameters:
- conn - a pointer to an instance of the SednaConnection type.
Return values:
- SEDNA_CONNECTION_OK - specified connection is open and functions ok.
- SEDNA_CONNECTION_CLOSED - specified connection is closed. This could be
either after the call to SEclose function, or before the call to SEconnect
function.
- SEDNA_CONNECTION_FAILED - specified connection has been failed. (Note:
in this case you should call SEclose function to release resources).
An application may obtain the transaction status by SEtransactionStatus
function:
int SEtransactionStatus(SednaConnection* conn)
Parameters:
- conn - a pointer to an instance of the SednaConnection type.
Return values:
- SEDNA_TRANSACTION_ACTIVE - specified connection runs transaction.
- SEDNA_NO_TRANSACTION - specified connection does not run transaction.
This could be for example when previous transaction has been committed
and a new one has not begun yet.
1.2.6 Executing Queries and Updates
There are two functions to execute a statement (query or update): SEexecute function
and SEexecuteLong function. First one reads statement from a C-string, the second
reads long statement from a provided file. To get trace (fn:trace XQuery function) and
debug information application may implement custom debug handler and set it using
function: SEsetDebugHandler.
int SEexecute(SednaConnection* conn, const char* query)
Parameters:
- conn - a pointer to an instance of the SednaConnection type.
- query - a null-terminated string with an XQuery or XUpdate statement.
Return values:
If the function succeeds, the return value is positive:
- SEDNA_QUERY_SUCCEEDED - specified query succeeded and result data can be
retrieved.
- SEDNA_UPDATE_SUCCEEDED - specified update succeeded.
- SEDNA_BULK_LOAD_SUCCEEDED - specified update (bulk load 2.4) succeeded.
If the function fails, the return value is negative:
- SEDNA_QUERY_FAILED - specified query failed.
- SEDNA_UPDATE_FAILED - specified update failed.
- SEDNA_BULK_LOAD_FAILED - bulk load failed.
- SEDNA_ERROR - some error occurred.
If the statement is really long, and you prefer to pass it to the Sedna directly from a
file use SEexecuteLong function.
int SEexecuteLong(SednaConnection* conn,
const char* query_file_path)
Parameters:
- conn - a pointer to an instance of the SednaConnection type.
- query_file - a path to the file with a statement to execute.
Return values:
If the function succeeds, the return value is positive:
- SEDNA_QUERY_SUCCEEDED - specified query succeeded and result data can be
retrieved.
- SEDNA_UPDATE_SUCCEEDED - specified update succeeded.
- SEDNA_BULK_LOAD_SUCCEEDED - specified update (bulk load 2.4) succeeded.
If the function fails, the return value is negative:
- SEDNA_QUERY_FAILED - specified query failed.
- SEDNA_UPDATE_FAILED - specified update failed.
- SEDNA_BULK_LOAD_FAILED - bulk load failed.
- SEDNA_ERROR - some error occurred.
If SEexecute function or SEexecuteLong function return SEDNA_QUERY_SUCCEEDED,
the result data can be retrieved. The result of XQuery query evaluation is a sequence of
items, where every item is represented as a string. Use the SEnext function to iterate
over the sequence and SEgetData function to retrieve the current item of the
sequence.
int SEnext(SednaConnection* conn)
Parameters:
- conn - a pointer to an instance of the SednaConnection type.
Return values:
If the function succeeds, the return value is positive:
- SEDNA_NEXT_ITEM_SUCCEEDED - moving to the next item succeeded, and the
item can be retrieved.
If the function fails or the is no result items available to retrieve, the return value is
negative:
- SEDNA_NEXT_ITEM_FAILED - failed to get next item.
- SEDNA_RESULT_END - the result sequence is ended, no result data to retrieve.
- SEDNA_NO_ITEM - there was no succeeded query that produced the result
data, no result data to retrieve.
- SEDNA_ERROR - some error occurred.
SEgetData function retrieves current item from the result sequence:
int SEgetData(SednaConnection* conn,
char* buf,
int bytes_to_read)
Parameters:
- conn - a pointer to an instance of the SednaConnection type.
- buf - pointer to the buffer that receives the data got from the server.
- bytes_to_read - number of bytes to be read from the server into the buffer.
Return values:
If the function succeeds, the return value is non-negative:
- number of bytes actually read from the server and put into the buffer.
- zero - no data was read from the server and put into the buffer because of
the item end. (use SEnext to move to the next item of the result).
If the function fails, the return value is negative:
- SEDNA_GET_DATA_FAILED - failed to get data.
- SEDNA_ERROR - some error occurred.
Since version 1.5 Sedna supports reporting tracing information (fn:trace XQuery
function). To handle tracing information while retrieving result data use debug handler
debug_handler_t and SEsetDebugHandler function:
void SEsetDebugHandler(struct SednaConnection *conn,
debug_handler_t debug_handler)
Parameters:
- conn - a pointer to an instance of the SednaConnection type.
- debug_handler - a pointer to your own defined function of the following
type: void (*debug_handler_t)(int subtype, const char *msg)
where subtype is a type of debug information (currently only
SEDNA_QUERY_TRACE_INFO is supported), msg is a buffer with debug
information.
For example the following debug handler prints out debug iformation to the
stdout:
void my_debug_handler(enum SEdebugType subtype,
const char *msg) {
printf("TRACE: ");
printf("subtype(%d), msg: %s\n", subtype, msg);
}
If the debug handler is not defined by the application, trace information is
ignored.
1.2.7 Loading Data
XML data can be loaded into a database using "LOAD" statement of the Data
Manipulation Language (see 2.4). Besides, libsedna library provides SEloadData and
SEendLoadData functions to load well-formed XML documents divided into parts of any
convenient size.
SEloadData functions loads a chunk of an XML document:
int SEloadData(SednaConnection* conn,
const char* buf,
int bytes_to_load,
const char* doc_name,
const char* col_name)
Parameters:
- conn - a pointer to an instance of the SednaConnection type.
- buf - a buffer with chunk of an XML document to load.
- bytes_to_load - number of bytes to load.
- doc_name - name of the document in a database the data loads to.
- col_name - name of the collection in the case if document is loaded into the
collection, NULL if document is loaded as a standalone one.
Return values:
If the function succeeds, the return value is positive:
- SEDNA_DATA_CHUNK_LOADED - chunk of an XML document loaded
successfully.
If the function fails, the return value is negative:
- SEDNA_ERROR - some error occurred. Data is not loaded.
When the whole document is loaded using SEloadData, application must use
SEendLoadData to notify server that transfer of an XML document is finished:
int SEendLoadData(SednaConnection* conn)
Parameters:
- conn - a pointer to an instance of the SednaConnection type.
Return values:
If the function succeeds, the return value is positive:
- SEDNA_BULK_LOAD_SUCCEEDED - XML document was successfully loaded into
the database.
If the function fails, the return value is negative:
- SEDNA_BULK_LOAD_FAILED - failed to load XML document into the database.
- SEDNA_ERROR - some error occurred.
1.2.8 Example Code
#include "libsedna.h"
#include "stdio.h"
int handle_error(SednaConnection* conn,
const char* op,
int close_connection) {
printf("%s failed: \n%s\n", op, SEgetLastErrorMsg(conn));
if(close_connection == 1) SEclose(conn);
return -1;
}
int main() {
struct SednaConnection conn = SEDNA_CONNECTION_INITIALIZER;
int bytes_read, res, value;
char buf[1024];
/* Turn off autocommit mode */
value = SEDNA_AUTOCOMMIT_OFF;
res = SEsetConnectionAttr(&conn, SEDNA_ATTR_AUTOCOMMIT,
(void*)&value, sizeof(int));
/* Connect to the database */
res = SEconnect(&conn, "localhost", "test_db",
"SYSTEM", "MANAGER");
if(res != SEDNA_SESSION_OPEN)
return handle_error(&conn, "Connection", 0);
/* Begin a new transaction */
res = SEbegin(&conn);
if(res != SEDNA_BEGIN_TRANSACTION_SUCCEEDED)
return handle_error(&conn, "Transaction begin", 1);
/* Load file "region.xml" into the document "region" */
res = SEexecute(&conn, "LOAD ’region.xml’ ’region’");
if(res != SEDNA_BULK_LOAD_SUCCEEDED)
return handle_error(&conn, "Bulk load", 1);
/* Execute XQuery statement */
res = SEexecute(&conn, "doc(’region’)/*/*");
if(res != SEDNA_QUERY_SUCCEEDED)
return handle_error(&conn, "Query", 1);
/* Iterate and print the result sequence */
while((res = SEnext(&conn)) != SEDNA_RESULT_END) {
if (res == SEDNA_ERROR)
return handle_error(&conn, "Getting item", 1);
do {
bytes_read = SEgetData(&conn, buf, sizeof(buf) - 1);
if(bytes_read == SEDNA_ERROR)
return handle_error(&conn, "Getting item", 1);
buf[bytes_read] = ’\0’;
printf("%s\n", buf);
} while(bytes_read > 0);
}
/* Drop document "region" */
res = SEexecute(&conn, "DROP DOCUMENT ’region’");
if(res != SEDNA_UPDATE_SUCCEEDED)
return handle_error(&conn, "Drop document", 1);
/* Commit transaction */
res = SEcommit(&conn);
if(res != SEDNA_COMMIT_TRANSACTION_SUCCEEDED)
return handle_error(&conn, "Commit", 1);
/* Close connection */
res = SEclose(&conn);
if(res != SEDNA_SESSION_CLOSED)
return handle_error(&conn, "Close", 0);
return 0;
}
The full version of this example program can be found in:
[win:] INSTALL_DIR\examples\api\c\Client.c
[nix:] INSTALL_DIR/examples/api/c/Client.c
Here 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:
- Start Sedna by running the following command:
se_gov
If Sedna is started successfully it prints ”GOVERNOR has been started in the
background mode”.
- 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”.
- 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”.
You can compile and run the example by following the steps listed below:
- To compile the example use:
[win:] Clientbuild.bat
[nix:] ./Clientbuild.sh
located in the same folder as Client.c.
- To run the compiled example use:
[win:] Client.exe
[nix:] ./Client
located in the same folder as Client.c.
|