Quick Start with Embedded eXtremeSQL in C

The eXtremeSQL C Language API allows developers to call low level C functions to initialize, open and close the SQL engine, and execute statements directly (without the use of C++ wrapper classes). Once initialized, the SQL engine is passed to function mcosql_execute_statement() for SQL insert, update and delete statements and to function mcosql_execute_query() for database queries. The following sections will walk through the steps for building a simple C eXtremeSQL application. In addition, note that there are many C SDK samples that demonstrate specific eXtremeSQL features.

Database definition

For C applications, the database itself is defined in an external schema file and compiled by mcocomp to produce the schema-specific database interface files that will be included in our C project. For this example application we will use a schema file schema.mco as follows:

 
    declare database  persondb;
     
    class Person
    {
        string name;
        unsigned<4>  ordinal;
         
        autoid[1000];
        tree<name> pk;
    };
     

We run mcocomp to compile the schema specifying the -sql option as follows:

 
    eXtremeDB/host/bin/mcocomp -sql schema.mco 
 

This produces files persondb.h which we will include in our application source file main.c, and persondb.c which will be compiled and linked to our application.

Open the database for SQL access

To open the database for SQL access we first create an in-memory database and connect to it as with any eXtremeDB application. Then we pass the database connection handle to mcoapi_create_engine() which initializes the SQL interface handle engine. (To avoid unnecessary complication of this example we will hide these details and simply call function initialize_db() to perform the initial database creation and connection.)

To complete this step we will call mcoapi_destroy_engine() to terminate the SQL database interface. The sample code for main.c so far looks like this:

 
    #include "persondb.h"
     
    const char * db_name = "persondb";
    #define DATABASE_SIZE 100 * 1024 * 1024
    #define MEMORY_PAGE_SIZE 256
     
    int main(int argc, char* argv[])
    {
        MCO_RET           rc;
        mco_db_h          db;
        database_t        engine;
         
        rc = initialize_db(&db, db_name, DATABASE_SIZE, MEMORY_PAGE_SIZE);
         
        if ( MCO_S_OK == rc ) 
        {
            rc = (MCO_RET)mcoapi_create_engine(db, &engine);
            
            if ( MCO_S_OK == rc ) 
            {
                /* Do database processing ... */
                 
                /* Destroy the SQL engine and disconnect from and close database */
                rc = (MCO_RET)mcoapi_destroy_engine( engine );
            }
            rc = mco_db_disconnect(db);
            rc = mco_db_close(db_name);
        }
    }
 

Populate and query the database

To populate the database we execute some SQL insert statements by calling the mcosql_execute_statement() function as follows:

         
        rc = (MCO_RET)mcosql_execute_statement(engine, NULL, NULL, "insert into Person values('Luke Skywalker', 0)");
        rc = (MCO_RET)mcosql_execute_statement(engine, NULL, NULL, "insert into Person values('Han Solo', 1)");
         

Then to query the database we call mco_execute_query() to return the data_source_t structure result:

         
         
        data_source_t result = NULL;
         
        rc = (MCO_RET)mcosql_execute_query(engine, NULL, &result, "select * from Person") );
         

Processing query results

The data_source_t structure returned from mcosql_execute_query() is a dataset for which there are numerous functions for extracting the result rows and information about the columns, etc. But presenting these details is beyond the scope of this quick start demonstration. Please see QueryResult processing for details and the SQL_C SDK samples for several examples.