CTWave Programming Notes

CTWave is a CT-Lib interface to Sybase. The goal of this library is to provide a simple, fast, and consistent interface to the database. The two most common methods of database access are embedded SQL and Dynamic SQL. Embedded SQL must be placed directly in the code or placed through macros and then pre-processed. This leads to unreadable code and difficult debugging. Dynamic SQL is easily readable and written quickly but will not scale. The CTWave database library strives to overcome these problems and allows the programmer to have no knowledge of the SQL client library.

The heart of the library are the query functions.

CTWave Programming Basics

Your basic CTWave program will look something like this:

#include ctwave/ctwave.h
#include ctwave/ctwave-query.h
#include ctwave/ctwave-database.h
#include ctwave/ctwave-context.h

#include stdio.h
#include glib.h

int main(int argc, char *argv[]) {
  CTWaveDatabase *db;
  CTWaveQuery    *query;

  gchar column_vc[256];
  gint  column_int;
  gchar column_c[3];
  gchar column_date[64];

  gboolean fetch;

  ctwave_query_start();
 
  db = ctwave_database_new(0);

  if (ctwave_database_ready(db,0,"username","password","server",0)
       == WAVE_FAIL) {
    g_warning("DB ctwave_database_ready failed...\n");
    return 1;
  }
  
  if (ctwave_connection_connect() == WAVE_FAIL) {
    g_warning("DB ctwave_connection failed...\n");
    return 1;
  }

  query = ctwave_query_new("select_sysobjects");


  if (ctwave_query_prepare(query,
      "select name,id,type,convert(varchar(32),crdate,9) \"d\" from sysobjects \
       where type = %s",
      FALSE) == WAVE_FAIL) {
    g_warning("DB ctwave_query_prepare failed...\n");
    return;
  }

  if (ctwave_query_open(query, NULL, "S") == WAVE_FAIL) {
    g_warning("DB ctwave_query_open failed...\n");
    return;
  }

  while ((fetch = ctwave_query_sfetch(query)))  {
    ctwave_query_read(query, "%s(name)%ld(id)%s(type)%s(d)",
      column_vc, _int,column_c,column_date);
    printf("%s\t%d\t%s\t%s\n",column_vc,column_int,column_c,column_date);
  }
    
  ctwave_query_close(query,FALSE);

  ctwave_query_del(query);

  ctwave_connection_disconnect(TRUE);

  ctwave_database_del(db);

  ctwave_query_stop();

  ctwave_context_stop();

  return 0;
}

This example will read a text column from a table:

#include ctwave/ctwave.h
#include ctwave/ctwave-query.h
#include ctwave/ctwave-database.h
#include ctwave/ctwave-context.h
#include ctwave/ctwave-blob-id.h

#include stdio.h
#include glib.h

int main(int argc, char *argv[]) {
  CTWaveDatabase *db;
  CTWaveQuery    *query;
  gint            column_int,i;
  CTWaveBlobId   *blob = ctwave_blob_id_new();
  WaveMemBuf      membuf;
  gboolean        fetch;

  membuf.data = 0;
  membuf.size = 0;

  ctwave_query_start();
 
  db = ctwave_database_new(0);

  if (ctwave_database_ready(db,0,"username","password","server",0)
       == WAVE_FAIL) {
    g_warning("DB ctwave_database_ready failed...\n");
    return 1;
  }
  
  if (ctwave_connection_connect() == WAVE_FAIL) {
    g_warning("DB ctwave_connection failed...\n");
    return 1;
  }

  query = ctwave_query_new("select_text");


  if (ctwave_query_prepare(query, "select id,data from sys_table_text",
			   FALSE) == WAVE_FAIL) {
    g_warning("DB ctwave_query_prepare failed...\n");
    return;
  }

  if (ctwave_query_open(query, NULL, "SYS Text Test") == WAVE_FAIL) {
    g_warning("DB ctwave_query_open failed...\n");
    return;
  }
    
  while ((fetch = ctwave_query_sfetch(query)))  {
    ctwave_query_read(query, "%ld(id)%Q(data)",
	_int,blob);
    ctwave_blob_id_get(blob, );  
    printf("%d\t%s\n",column_int,membuf.data);
  }

  ctwave_query_close(query,FALSE);
  
  ctwave_blob_id_del(blob);

  g_free(membuf.data);

  ctwave_query_del(query);

  ctwave_connection_disconnect(TRUE);

  ctwave_database_del(db);

  ctwave_query_stop();

  ctwave_context_stop();

  return 0;
}

This example will update a column in a table:

#include ctwave/ctwave.h
#include ctwave/ctwave-query.h
#include ctwave/ctwave-database.h
#include ctwave/ctwave-context.h

#include stdio.h
#include glib.h

int main(int argc, char *argv[]) {
  CTWaveDatabase *db;
  CTWaveQuery    *query;
  gint            column_int;
  gchar           column_c[3];

  strcpy(column_c,"R");
  column_int = 45;

  ctwave_query_start();
 
  db = ctwave_database_new(0);

  if (ctwave_database_ready(db,0,"username","password","server",0)
       == WAVE_FAIL) {
    g_warning("DB ctwave_database_ready failed...\n");
    return 1;
  }
  
  if (ctwave_connection_connect() == WAVE_FAIL) {
    g_warning("DB ctwave_connection failed...\n");
    return 1;
  }

  query = ctwave_query_new("update_sys_table");

  if (ctwave_query_prepare(query, "update sys_table set type = %s, id = %d",
			   FALSE) == WAVE_FAIL) {
    g_warning("DB ctwave_query_prepare failed...\n");
    return;
  }

  ctwave_query_execute(query,NULL,column_c,column_int);

  ctwave_query_del(query);

  ctwave_connection_disconnect(TRUE);

  ctwave_database_del(db);

  ctwave_query_stop();

  ctwave_context_stop();

  return 0;
}

The following identifiers are defined:


  %s    -    char*
  %d    -    int
  %hd   -    short
  %HD   -    short*
  %ld   -    long
  %lD   -    long*
  %f    -    float
  %F    -    float*
  %lf   -    double
  %lF   -    double*
  %Q    -    CTWaveBlobId*

  Memory Buffer used by Blobs.

  struct WaveMemBuf {
    gchar *data;
    gint   size;
  };

To compile the program, we would use the following:

cc -o testprogram testprogram.c `ctwave-config --cflags --libs`

The ctwave-config script will give the correct parameters used to compile the program. If you are using automake or autoconf, you may want to investigate the AM_PATH_CTWAVE macro that is installed as $(datadir)/aclocal/ctwave.m4.