Mimer SQL Programmer's Manual TOC PREV NEXT INDEX

Mimer Developer Site

www.mimer.com/developer


DSQLSAMP Program Using Dynamic SQL


The DSQLSAMP program demonstrates how a C program can be constructed using dynamic SQL syntax according to international standards.

The source code file for the DSQLSAMP program is dsql.ec which contains a collection of routines that define a simple but convenient API for dynamic SQL, which can be called from other C programs.

The dsqlsamp.c file contains a program that calls the routines defined in dsql.ec. The DSQLSAMP program allows the user to enter an SQL statement that will be executed directly, in a manner similar to the BSQL program, see the Mimer SQL User's Manual for details about BSQL.

Building the DSQLSAMP Program

UNIX: The following example assumes Mimer SQL is installed in the directory /opt/mimer821A and illustrates how the DSQLSAMP program is compiled and built by using the distributed example makefile:
 $ mkdir dsql # Do everything in a sub directory
 $ cd dsql
 $ cp /opt/mimer821A/examples/ex_makefile ./makefile
 $ cp /opt/mimer821A/examples/dsql* .
 
Take a copy of the makefile and update it so that the MYPROG symbol is set to "dsqlsamp" and the MYFUNCS symbol is set to "dsql.o" (avoid trailing spaces).
 MYPROG = dsqlsamp
 MYFUNCS = dsql.o
Then make the dsqlsamp program:
 $ export MIMER_HOME=/opt/mimer821A
 $ make

VMS: The following example illustrates how the DSQLSAMP program is compiled and linked under VMS. The program is supplied in C.
 $ ESQL/C MIMEXAMPLES8:DSQL                 ! Preprocess source code
 $ COPY MIMEXAMPLES8:DSQL.H SYS$DISK:[]     ! Get header file
 $ COPY MIMEXAMPLES8:DSQLSAMP.C SYS$DISK:[] !Get main program
 $ CC DSQL                                  ! Compile preprocessed code
 $ CC DSQLSAMP                              ! Compile sample program
 $ LINK DSQLSAMP,DSQL,MIMLIB8:MIMER/OPT     ! Link executable prog

Win: On Windows platforms, the examples files are installed in the dev directory which is located below the installation directory. The dev directory contains a makefile called makefile.mak, which will build all the example programs at the same time. The examples have been tested using Microsoft Visual C.
These instructions assume that Microsoft Visual C is used and that the make command is being executed from the dev directory, appropriate adjustments must be made if this is not the case.
$ nmake -f makefile.mak

Source Code for the DSQLSAMP Program in C

 
 /********************************************************************/
 /*  dsqlsamp.c - sample program using dynamic SQL driver            */
 /********************************************************************/
 /*                                                                  */
 /*               Simple command line oriented SQL executor          */
 /*                                                                  */
 /********************************************************************/
 /*                                                                  */
 /*  Created by Upright Database Technology AB                       */
 /*                                                                  */
 /* You have a free right to use, modify, reproduce, and distribute  */
 /* the sample files (and/or any modified version) in any way you    */
 /* find useful, provided that you agree that Upright Database       */
 /* Technology AB has no warranty obligations or liability for any   */
 /* sample files which are modified.                                 */
 /*                                                                  */
 /********************************************************************/
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include "dsql.h"       /* function prototype definitions */
 
 static   char  sqlbuf [4096];
 
 static   void  error  ();
 static   void  getid  (char* prompt,char* text);
 static   char* savres (char* result,char* sqlbuf);
 static   int*  savlen (int* collen,int colcount,char* sqlbuf);
 static   void  show   (char* result,int rowcount,int* collen,int colcount);
 
 /********************************************************************/
 int main()
 /********************************************************************/
 {
     char  database [129];
     char  username [129];
     char  password [19];
     char* p;
     char* result;
     int*  collen;
     int   rc;
     int   cursor;
     int   colcount;
     int   rowcount;
 
     printf("\n  *** Welcome to Mimer Dynamic SQL Sample Program ***\n\n");
     /*
      *  Connect to database
      */
     for (;;)
     {
         getid("Database:",database);
         getid("Username:",username);
         getid("Password:",password); /* NOTE: password is not hidden!*/
         printf(" \n");
         if ((rc = DsqlConnect(database,username,password)) > 0) break;
         if (rc < 0) error(), exit(0);
         printf("You have entered wrong username or password.\n");
         printf("Please, try again.\n\n");
     }
     printf(" - End an SQL statement with ';'\n");
     printf(" - Exit the program by giving an empty command\n\n");
     /*
      *  SQL command loop
      */
     for (;;)
     {
         /*
          *  Read an SQL statement ending with ';'
          */
         printf("SQL>");     /* Display command prompter   */
         for (p = sqlbuf;; p++, *p++ = ' ')
         {
             *p = '\0';
             fgets(p,255,stdin);
             p += strlen(p);
             while ((*p == '\0' || *p == ' ') && p > sqlbuf) p--;
             if (*sqlbuf == '\0' || *p == ';') break;
             printf("   >");
         }
         printf(" \n");
         if (*p == '\0')     /* Empty command, ask if exit */
         {
             printf("Quit? (y/n) ");
             fgets(p,255,stdin);
             printf(" \n");
             if (*p == 'y' || *p == 'Y') break;
             continue;
         }
         *p = '\0';          /* Eliminate the ending ';'   */
         /*
          *  Execute SQL-statement
          */
         cursor = DsqlExecute(sqlbuf);
         if (cursor > 0)
         {
             /*
              *  It was a select statement, get column names
              */
           if ((colcount = DsqlColNames(cursor,sqlbuf,sizeof(sqlbuf))) > 0)
             {
                 result = savres(NULL,sqlbuf);
                 collen = savlen(NULL,colcount,sqlbuf);
                 /*
                  *  Fetch the resulting rows into memory and
                   *  calculate the minimum possible width of the columns
                  */
                 rowcount = 0;
                 while ((rc = DsqlFetch(cursor,sqlbuf,sizeof(sqlbuf))) > 0)
                 {
                     result = savres(result,sqlbuf);
                     collen = savlen(collen,colcount,sqlbuf);
                     rowcount++;
                 }
                 if (rc < 0 || DsqlClose(cursor) < 0) error();
                 /*
                  *  Show the result set nicely formatted
                  */
                 show(result,rowcount,collen,colcount);
             }
             else
             {
                 error();
             }
         }
         else if (cursor == 0)
         {
             printf("*** SQL statement executed successfully! ***\n\n");
         }
         else
         {
             error();
         }
     }
     /*
      *  Disconnect and exit
      */
     if (DsqlDisconnect() < 0) error();
     printf(" *** Exit from Mimer Dynamic SQL Sample Program ***\n\n");
     exit(0);
     return 0;
 }
 
 /********************************************************************/
 /*                                                                  */
 /*  Print SQL error message                                         */
 /*                                                                  */
 /********************************************************************/
 static void error()
 /********************************************************************/
 {
     DsqlError(sqlbuf,sizeof(sqlbuf));
     printf("%s\n",sqlbuf);
 }
 
 /********************************************************************/
 /*                                                                  */
 /*  Prompt for connect identifiers                                  */
 /*                                                                  */
 /********************************************************************/
 static void getid(char* prompt,char* text)
 / *******************************************************************/
 {
     printf("%s",prompt);
     sqlbuf[0] = '\0';
     fgets(sqlbuf,255,stdin);
     sqlbuf[128] = '\0';
     strcpy(text,sqlbuf);
 }
 
 /********************************************************************/
 /*                                                                  */
 /*  Save a result row in memory                                     */
 /*                                                                  */
 /********************************************************************/
 static char* savres(char* result,char* sqlbuf)
 /********************************************************************/
 {
     static int reslen;
            int buflen = strlen(sqlbuf) + 1;
 
     if (result == NULL)
     {
         result = malloc(buflen + buflen - 1);
         memcpy(result,sqlbuf,buflen);
         reslen = buflen - 1;
     }
     else if((result = realloc(result,reslen + buflen)) == NULL)
     {
       printf("** Fatal: not enough memory, exiting... **\n\n");
       exit(0);
     }
     memcpy(&result[reslen],sqlbuf,buflen);
     reslen += buflen - 1;
     return result;
 }
 
 /********************************************************************/
 /*                                                                  */
 /*  Keep track of the minimum possible width of the columns         */
 /*                                                                  */
 /********************************************************************/
 static int* savlen(int* collen,int colcount,char* sqlbuf)
 /********************************************************************/
 {
     char* p = strtok(sqlbuf,"\t\n");
     int   i,n;
 
     if (collen == NULL) collen = calloc(sizeof(int),colcount);
     for (i = 0; i < colcount; i++)
     {
         n = p ? strlen(p) : 0;
         if (collen[i] < n) collen[i] = n;
         p = strtok(NULL,"\t\n");
     }
     return collen;
 }
 
 /********************************************************************/
 /*                                                                  */
 /*  Print the formatted result set and release memory               */
 /*                                                                  */
 /********************************************************************/
 static void show(char* result, int rowcount, int* collen, int colcount)
 /********************************************************************/
 {
     char* p = strtok(result,"\t\n");
     int   i,n,pos;
 
     printf("*** %d row%s selected ***\n\n", rowcount, rowcount == 1 ? "" : "s");
     for (n = 0; n < rowcount + 2; n++)
     {
         pos = 0;
         memset(sqlbuf,' ',sizeof(sqlbuf));
         for (i = 0; i < colcount; i++)
         {
             if (p) memcpy(&sqlbuf[pos],p,strlen(p));
             if (n == 1) memset(&sqlbuf[pos],'=',collen[i]);
             p = strtok(NULL,"\t\n");
             pos += collen[i] + 1;
         }
         sqlbuf[pos] = '\0';
         printf("%s\n",sqlbuf);
     }
     printf("\n");
     free(result);
     free(collen);
 }
 
 /********************************************************************/
 /* dsql.h                                                           */
 /********************************************************************/
 
 #ifndef DSQL_H
 #define DSQL_H
 
 int DsqlConnect    (char* database,char* userid,char* passwd);
 int DsqlDisconnect (void);
 int DsqlExecute    (char* sql);
 int DsqlColNames   (int stmt,char* buffer,int len);
 int DsqlFetch      (int stmt,char* buffer,int len);
 int DsqlClose      (int stmt);
 int DsqlError      (char* message,int len);
 
 #endif
 /********************************************************************/
 /*  dsql.ec - dynamic SQL driver                                    */
 /********************************************************************/
 /*                                                                  */
 /* This package is a DSQL sample with the following functions:      */
 /*                                                                  */
 /*      DsqlConnect    - connect to the database                    */
 /*      DsqlDisconnect - disconnect from the database               */
 /*      DsqlExecute    - execute an SQL statement                   */
 /*      DsqlColNames   - get the column names of a result table     */
 /*      DsqlFetch      - fetch the next row from a result table     */
 /*      DsqlClose      - close a cursor                             */
 /*      DsqlError      - get error message text                     */
 /*                                                                  */
 /********************************************************************/
 /*                                                                  */
 /*  Created by Upright Database Technology AB.                      */
 /*                                                                  */
 /* You have a free right to use, modify, reproduce, and distribute  */
 /* the sample files (and/or any modified version) in any way you    */
 /* find useful, provided that you agree that Upright Database       */
 /* Technology AB has no warranty obligations or liability for any   */
 /* sample files which  are modified.                                */
 /*                                                                  */
 /********************************************************************/
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include "dsql.h"       /* function prototype definitions */
 
 #define TRUE  1
 #define FALSE 0
 
 /*
  *  VARCHAR data type definition
  */
 #define SQL_VARCHAR 12
 /*
  *  SQLSTATE return code definitions
  */
 #define SQL_SUCCESS                            "00000"
 #define SQL_INSUFFICIENT_ITEM_DESCRIPTOR_AREAS "01005"
 #define SQL_NO_DATA                            "02000"
 #define SQL_CONNECTION_REJECTED                "28000"
 /*
  *  Shared data areas
  */
 exec sql begin declare section;
 static char statement  [129];       /* Extended statement name */
 static char cursor     [129];       /* Extended cursor name    */
 static char descriptor [129];       /* SQL descriptor name     */
 static char sqlstate   [6];         /* SQLSTATE                */
 static char buffer     [8192];      /* Data buffer             */
 exec sql end declare section;
 
 static int  seqno = 0;    /*Sequence number for generating unique names */
 /********************************************************************/
 /*                                                                  */
 /*  Connect to the database.                                        */
 /*  Parameters:                                                     */
 /*                                                                  */
 /*  Return codes:                                                   */
 /*                                                                  */
 /*      1 : successful connection                                   */
 /*      0 : wrong username or password                              */
 /*     -1 : error (call DsqlError for message text)                 */
 /********************************************************************/
 int DsqlConnect()
 /********************************************************************/
 {
     exec sql whenever sqlerror goto exception;
     exec sql begin declare section;
     char  database [129] = "";
     char  username [129] = "";
     char  password [19] = "";
     exec sql end declare section;
     char* p;
 
     getid("Database:",database);
     getid("Username:",username);
     getid("Password:",password);  /* NOTE: password is not hidden! */
 
     /*
      *  Connect to database.
      */
     for (p = username; *p; p++) *p = (char)toupper((int)*p);
 
     exec sql connect to :database user :username using :password;
 
     return 1;
 
 exception:
 
     if (strcmp(sqlstate, SQL_CONNECTION_REJECTED) == 0)
     {
         return 0;
     }
     return -1;
 }
 /********************************************************************/
 /*                                                                  */
 /*  Disconnect from the database.                                   */
 /*                                                                  */
 /*  Return codes:                                                   */
 /*                                                                  */
 /*      0 : OK                                                      */
 /*     -1 : error (call DsqlError for message text)                 */
 /*                                                                  */
 /********************************************************************/
 int DsqlDisconnect()
 /********************************************************************/
 {
     exec sql whenever sqlerror goto exception;
 
     exec sql disconnect;
     return 0;
 
 exception:
 
     return -1;
 }
 
 /********************************************************************/
 /*                                                                  */
 /*  Execute an SQL statement.                                       */
 /*                                                                  */
 /*  Parameter:                                                      */
 /*                                                                  */
 /*      char* sqlstmt : SQL statement to be executed                */
 /*                                                                  */
 /*  Return codes:                                                   */
 /*                                                                  */
 /*     +n : a select statement successfully opened,                 */
 /*          returning a cursor identifier                           */
 /*      0 : a non-select statement executed successfully            */
 /*     -1 : error (call DsqlError for message text)                 */
 /*                                                                  */
 /*  Note:                                                           */
 /*                                                                  */
 /*   It is assumed that the SQL statement does not contain any      */
 /*   parameter markers. Unique statement, descriptor, and cursor    */
 /*   names are used, which make it possible to have several cursors */
 /*   open at the same time.                                         */
 /*                                                                  */
 /********************************************************************/
 int DsqlExecute(char* sqlstmt)
 /********************************************************************/
 {
     exec sql whenever sqlerror goto exception;
     exec sql begin declare section;
     int  count;
     int  n;
     int  type;
     int  length;
     exec sql end declare section;
 
     /*
      *  Check argument.
      */
     if (sqlstmt == NULL) return -1;
     /*
      *  Make unique statement and descriptor names.
      */
     seqno++;
     sprintf(statement, "%d",seqno);
     sprintf(descriptor,"%d",seqno);
     /*
      *  Copy SQL statement to buffer.
      */
     strncpy(buffer,sqlstmt,sizeof(buffer));
     buffer[sizeof(buffer) - 1] = '\0';
     /*
      *  Prepare SQL statement.
      */
     exec sql prepare :statement from :buffer;
     /*
      *  Allocate descriptor.
      */
     exec sql allocate descriptor :descriptor;
     /*
      *  Describe output.
      */
     exec sql describe output :statement
              using sql descriptor :descriptor;
     if (strcmp(sqlstate, SQL_INSUFFICIENT_ITEM_DESCRIPTOR_AREAS) == 0)
     {
         /*
          *  The descriptor area was insufficient.
          *  Allocate a new one with appropriate size.
          */
         exec sql get descriptor :descriptor :count = count;
         exec sql deallocate descriptor :descriptor;
         exec sql allocate descriptor :descriptor
                  with max :count;
         exec sql describe output :statement
                  using sql descriptor :descriptor;
     }
     /*
      *  Get descriptor count to see if this was a select statement or not.
      */
     exec sql get descriptor :descriptor :count = count;
     if (count == 0)
     {
         /*
          *  Non-select statement. Execute.
          */
         exec sql execute :statement;
         /*
          *  Deallocate statement and descriptor.
          */
         exec sql deallocate prepare :statement;
         exec sql deallocate descriptor :descriptor;
         /*
          *  Return successful completion of non-select statement.
          */
         return 0;
     }
     else
     {
         /*
          *  Select statement. Set all columns to VARCHAR(512).
          *                    Mimer SQL automatic type conversion will
          *                    handle numeric data.
          */
         type   = SQL_VARCHAR;
         length = 512;
         for (n = 1; n <= count; n++)
         {
             exec sql set descriptor :descriptor value :n type   = :type,
                                                          length = :length;
         }
         /*
          *  Make a unique cursor name.
          */
         sprintf(cursor,"%d",seqno);
         /*
          *  Allocate and open cursor.
          */
         exec sql allocate :cursor cursor for :statement;
         exec sql open :cursor;
         /*
          *  Return cursor identifier.
          */
         return seqno;
     }
 
 exception:
     return -1;
 }
 /********************************************************************/
 /*                                                                  */
 /*  Get the column names of a result table.                         */
 /*                                                                  */
 /*  Parameters:                                                     */
 /*                                                                  */
 /*      int   c      : cursor identifier returned from DsqlExecute  */
 /*      char* record : buffer for the result string                 */
 /*      int   len    : length of the buffer (must be >= 32)         */
 /*                                                                  */
 /*  Return codes:                                                   */
 /*                                                                  */
 /*     +n : OK - number of columns                                  */
 /*     -1 : error (call DsqlError for message text)                 */
 /*                                                                  */
 /*  Note:                                                           */
 /*                                                                  */
 /*  The column names are returned in a tab ('\t') separated string  */
 /*  ending with a newline ('\n'). If the string is too large, it is */
 /*  truncated.                                                      */
 /*                                                                  */
 /********************************************************************/
 int DsqlColNames(int c,char* record,int len)
 /********************************************************************/
 {
     exec sql whenever sqlerror goto exception;
     exec sql begin declare section;
     int  count;
     int  n;
     char name [129];
     exec sql end declare section;
     int  length;
 
     /*
      *  Check arguments.
      */
     if (record == NULL || len < 32) return -1;
     /*
      *  Build descriptor name.
      */
     sprintf(descriptor,"%d",c);
     /*
      *  Get number of columns.
      */
     exec sql get descriptor :descriptor :count = count;
     for (n = 1; n <= count; n++)
     {
         /*
          *  Get one column name.
          */
         exec sql get descriptor :descriptor value :n
                  :name = name;
         /*
          *  Trim spaces and append a tab.
          */
         length = strlen(name);
         while (length > 1 && name[length - 1] == ' ') length--;
         if (length > len - 2) length = len - 2;
         memcpy(record,name,length);
         record += length;
         len    -= length;
         if (len == 2) break;
         if (n < count)
         {
             *record++ = '\t';
             len--;
         }
     }
     *record++ = '\n';
     *record   = '\0';
     return count;
 
 exception:
 
     return -1;
 }
 /********************************************************************/
 /*                                                                  */
 /*  Fetch the next row from a result table.                         */
 /*                                                                  */
 /*  Parameters:                                                     */
 /*                                                                  */
 /*      int   c      : cursor identifier returned from DsqlExecute  */
 /*      char* record : buffer for the result string                 */
 /*      int   len    : length of the buffer (must be >= 32)         */
 /*                                                                  */
 /*  Return codes:                                                   */
 /*                                                                  */
 /*     +n : OK - number of columns                                  */
 /*      0 : No more data (End of File)                              */
 /*     -1 : error (call DsqlError for message text)                 */
 /*                                                                  */
 /*  Note:                                                           */
 /*                                                                  */
 /*  The column values are returned in a tab ('\t') separated string */
 /*  ending with a newline ('\n'). It is assumed that the data does  */
 /*  not contain tab, newline or null characters. A column value of  */
 /*  NULL will be return as '?'. If the string is too large, it is   */
 /*  truncated.                                                      */
 /*                                                                  */
 /********************************************************************/
 int DsqlFetch(int c,char* record,int len)
 /********************************************************************/
 {
     exec sql whenever sqlerror goto exception;
     exec sql begin declare section;
     int  count;
     int  length;
     int  isnull;
     int  n;
     exec sql end declare section;
 
     /*
      *  Check arguments.
      */
     if (record == NULL || len < 32) return -1;
     /*
      *  Build cursor and descriptor names.
      */
     sprintf(cursor,    "%d",c);
     sprintf(descriptor,"%d",c);
     /*
      *  Fetch next row from result table.
      */
     exec sql fetch next from :cursor
              into sql descriptor :descriptor;
     if (strcmp(sqlstate,SQL_SUCCESS) == 0)
     {
         /*
          *  Get number of columns.
          */
         exec sql get descriptor :descriptor :count = count;
         for (n = 1; n <= count; n++)
         {
             /*
              *  Get one column value.
              */
             exec sql get descriptor  :descriptor value :n :buffer = data,
                                      :length = returned_length,
                                      :isnull = indicator;
             /*
              *  Check NULL indicator, trim spaces, append tab.
              */
             if (isnull == -1)
             {
                 *record++ = '?';
                  len--;
             }
             else
             {
                 while (length > 1 && buffer[length - 1] == ' ') length--;
                 if (length > len - 2) length = len - 2;
                 memcpy(record,buffer,length);
                 record += length;
                 len    -= length;
             }
             if (len == 2) break;
             if (n < count)
             {
                 *record++ = '\t';
                 len--;
             }
         }
         *record++ = '\n';
         *record   = '\0';
         return count;
     }
     else if (strcmp(sqlstate,SQL_NO_DATA) == 0)
     {
         /*
          *  No more data.
          */
         return 0;
     }
 
 exception:
 
     return -1;
 }
 /********************************************************************/
 /*                                                                  */
 /*  Close a cursor.                                                 */
 /*                                                                  */
 /*  Parameter:                                                      */
 /*                                                                  */
 /*      int c : cursor identifier returned from DsqlExecute         */
 /*                                                                  */
 /*  Return codes:                                                   */
 /*                                                                  */
 /*      0 : OK                                                      */
 /*     -1 : error (call DsqlError for message text)                 */
 /*                                                                  */
 /********************************************************************/
 int DsqlClose(int c)
 /********************************************************************/
 {
     exec sql whenever sqlerror goto exception;
 
     /*
      *  Build cursor, statement and descriptor names.
      */
     sprintf(cursor,    "%d",c);
     sprintf(statement, "%d",c);
     sprintf(descriptor,"%d",c);
     /*
      *  Close cursor.
      */
     exec sql close :cursor;
     /*
      *  Deallocate statement and descriptor.
      */
     exec sql deallocate prepare :statement;
     exec sql deallocate descriptor :descriptor;
     return 0;
 
 exception:
 
     return -1;
 }
 /********************************************************************/
 /*                                                                  */
 /*  Get error message text.                                         */
 /*                                                                  */
 /*  Parameters:                                                     */
 /*                                                                  */
 /*      char* message : buffer for the result string                */
 /*      int   len     : length of the buffer (must be >= 32)        */
 /*                                                                  */
 /*  Return codes:                                                   */
 /*                                                                  */
 /*      0 : OK                                                      */
 /*     -1 : error (cannot get message text)                         */
 /*                                                                  */
 /*  Note:                                                           */
 /*                                                                  */
 /*  The message text is returned in a newline ('\n') separated      */
 /*  string. If the string is too large, it is truncated.            */
 /*                                                                  */
 /********************************************************************/
 int DsqlError(char* message,int len)
 /********************************************************************/
 {
     exec sql whenever sqlerror goto exception;
     exec sql begin declare section;
     int   count;
     int   length;
     char  state [6]; /* returned_sqlstate may not be stored sqlstate */
     int   n;
     exec sql end declare section;
     char* p;
 
     /*
      *  Check arguments.
      */
     if (message == NULL || len < 32) return -1;
     /*
      *  Get number of errors.
      */
     exec sql get diagnostics :count = number;
     for (n = 1; n <= count; n++)
     {
         /*
          *  Get diagnostics of an error.
          */
         exec sql get diagnostics exception :n :buffer = message_text,
                                               :length = message_length,
                                               :state  = returned_sqlstate;
         /*
          *  Prepare message area.
          */
         if (length > len - 18) length = len - 18;
         memcpy(message,buffer,length);
         p = strchr(message,':');
         if (p) *p = '\n';
         if (length > 64)
         {
             p = strchr(&message[64],' ');
             if (p) *p = '\n';
         }
         message += length;
         len     -= length;
         *message++ = '\n';
         /*
          *  Add SQLSTATE code.
          */
         strcpy(message,"SQLSTATE:");
         message += 9;
         strcpy(message,state);
         message += 5;
         *message++ = '\n';
         *message++ = '\n';
         len -= 17;
         if (len < 32) break;
     }
     *message = '\0';
     return 0;
 
 exception:
 
     strcpy(message,"cannot get diagnostics\n\n");
     return -1;
 }
 


Upright Database Technology AB
Voice: +46 18 780 92 00
Fax: +46 18 780 92 40
dbtechnology@upright.se
Mimer SQL Programmer's Manual TOC PREV NEXT INDEX