HomeStartingEnvironmentDBMSVisualPQLProceduresSQLFormsHost/APIIndex
Host/API homecontents start chapter top of pagebottom of pagenext page index SIR/API

SIR API Overview

The SIR/APIs are two simple sets of five functions (one for SIRDBMS and one for SIRSQL). These APIs can be used to develop your own front-ends for SIR database management engines.

The INIT function initialise the system and defines two call back routines to handle the output from the API. The first of these callbacks (writeLine) handles output which would normally go to the main window, and the second (writeData) handles output from query type (LIST) commands. The initialise function also defines the start parameter string that you would normally use to start SIRDBMS or SIRSQL (eg: DB=COMPANY PW=COMPANY P=...). This initial function should be called first.

The EXEC function executes a DBMS or SQL command or set of commands.

The STOP function terminates the API, closing any open files and releasing handles. It should be called at the end of your program.

The other two functions return the VersionNumber (this one can be called before INIT) and the ERROR code. The latter can be called after any API function that has a FALSE return code.

Notes:

Your application will use SIR's DLLs, so the SIR's home directory must be included into your PATH (unless you place your executable file into that directory).

The system is not reenterable, so you must not call any of these functions before the previous call is completed. Also you cannot use both SirDBMS and SirSQL DLLs from the same application.

To compile your calls correctly under MS-Windows macro _WIN32 must be defined. It is predefined by Visual C++. Define it in your make file for other compilers. The macro will inforce __stdcall calling convention for the DLL's export names. You should use sirdbms.lib or sirsql.lib import library to link your application.

To write a console application that does not have a windows interface then use a window handle (hWnd) of (void *) 1.

homecontents start chapter top of pagebottom of pagenext page index

The DBMS Functions

SirDBMS_VersionNumber

int __StdCall SirDBMS_VersionNumber(void);
Returns DBMS engine's version number (40000 for 4.00.00). It's the only function you can execute before SirDBMS_Init().

SirDBMS_Init

int __StdCall SirDBMS_Init(
    void *hWnd,
    void (__StdCall *writeLine)(const char *text),
    void (__StdCall *writeData)(const char *text),
    const char *commandLine
);
Must be executed before sending commands to the DBMS engine.

The first argument is the system-specific handle of the main window. It should be the current window at this moment.

DBMS engine uses the function passed as the second argument to write a line of text into the message buffer. User interface module should immediately put the text into some output window.

DBMS engine uses the function passed as the third argument to write a line of text into the data buffer when given some query-type command.

The engine doesn't add any end-of-line terminators, it just makes one call for each line of output.

The last argument is a string which contains the command line arguments (without the leading application name).

Returns TRUE on success, FALSE on failure, doesn't return if the command line activates the batch mode.

SirDBMS_Exec

int __StdCall SirDBMS_Exec(void *hWnd, const char *commands);
Executes DBMS commands.

The first argument is the system-specific handle of the current window. It is used as the owner of the engine's message boxes.

The second argument is a DBMS command[s]. Multiple lines must be separated by '\n' character.

Returns TRUE on success, FALSE on failure.

SirDBMS_Stop

int __StdCall SirDBMS_Stop(void *hWnd);
Call this before you terminate the program.

The argument is the system-specific handle of the current window. It is used as the owner of the engine's message boxes.

This will properly disconnect and close all open files.

Returns TRUE on success, FALSE on failure.

SirDBMS_ErrorCode

int __StdCall SirDBMS_ErrorCode(void);
Call this to get the error code if one of the SirDBMS_... functions returned FALSE. Error code 0 means that information is not available.

homecontents start chapter top of pagebottom of pagenext page index

The DBMS LIST Commands

The LIST Commands are DBMS commands that send their output to the writeData callback routine.

homecontents start chapter top of pagebottom of pagenext page index

The SQL Functions

SirSQL_VersionNumber

int __StdCall SirSQL_VersionNumber(void);
Returns SQL engine's version number (40000 for 4.00.00). It's the only function you can execute before SirSQL_Init().

SirSQL_Init

int __StdCall SirSQL_Init(
    void *hWnd,
    void (__StdCall *writeLine)(const char *text),
    const char *commandLine
);
Must be executed before sending commands to the SQL engine.

The first argument is the system-specific handle of the main window. And it should be the current window at this moment.

SQL engine uses the function passed as the second argument to write a line of text into the output buffer. User interface module might immediately add the text into the output window or use results in some other way after it gets control back. The engine doesn't add any end-of-line terminators, it just makes one call for each line of output.

The last argument is a string which contains the command line arguments (without the leading application name).

Returns TRUE on success, FALSE on failure, doesn't return if the command line activates the batch mode.

SirSQL_Exec

int __StdCall SirSQL_Exec(void *hWnd, const char *commands);
Executes SQL commands.

The first argument is the system-specific handle of the current window. It is used as the owner of the engine's message boxes.

The second argument is a SQL command[s]. Multiple lines must be separated by '\n' character.

Returns TRUE on success, FALSE on failure.

SirSQL_Stop

int __StdCall SirSQL_Stop(void *hWnd);
Call this before you terminate the program.

The argument is the system-specific handle of the current window. It is used as the owner of the engine's message boxes.

This will properly disconnect and close all open files.

Returns TRUE on success, FALSE on failure.

SirSQL_ErrorCode

int __StdCall SirSQL_ErrorCode(void);
Call this to get the error code if one of the SirSQL_... functions returned FALSE.

The SQL LIST Commands

The LIST Commands in SQL correspond to the SHOW command but send their output to the writeData callback routine.

homecontents start chapter top of pagebottom of pagenext page index

Example Programs

ACME SQL

ACME SQL is a simple SQL interface that lets you enter SQL commands and view the output.

//**********************************************************************
//* AcmeSQL - example of using SirAPI (see readme.txt)                 *
//*                                                                    *
//* This software is provided as is, without any explicit or           *
//* implied warranties. Use it at your own risk.                       *
//**********************************************************************

#define STRICT
#include <windows.h>
#include <stdio.h>

#ifndef _WIN32
#define _WIN32
#endif

#include <sirapi.h>
#include "acmesql.rh"

const char *AppName = "AcmeSQL";
const char *IniFile = "acmesql.ini";

const int MinEngineVer = 41000;

int InpWndRatio = 30;
int AutoSave = FALSE;

HINSTANCE hInst;

HWND hFrame;
HWND hInpWnd;
HWND hOutWnd;

HFONT hFont;

char *GetInputText() {

    int length = GetWindowTextLength(hInpWnd);
    if (length == 0)
        return NULL;

    char *buffer = new char[length+1];

    length = GetWindowText(hInpWnd, buffer, length+1);

    int Empty = TRUE;
    for (int i=0; i<length; i++) if (!isspace(buffer[i])) {
        Empty = FALSE;
        break;
    }
    if (Empty) {
        delete buffer;
        return NULL;
    }

    return buffer;
}

void SetInputText(const char *text) {
    SetWindowText(hInpWnd, text);
}

void SetOutputText(const char *text) {
    SetWindowText(hOutWnd, text);
}

void AddToOutputWindow(const char *text) {

    int length = GetWindowTextLength(hOutWnd);
    int addlen = strlen(text);

    char *tmp = new char[addlen+2+1];
    memcpy(tmp, text, addlen);
    memcpy(tmp+addlen, "\r\n", 3);

    SendMessage(hOutWnd, EM_SETSEL, length, length);
    SendMessage(hOutWnd, EM_REPLACESEL, FALSE, (LPARAM)tmp);

    delete tmp;
}

void __StdCall OutputHandler(const char *text) {
    AddToOutputWindow(text);
}

int InitEngine(HWND hWnd, const char *CommandLine) {

    EnableWindow(hWnd, FALSE);

    int status = SirSQL_Init(hWnd, OutputHandler, CommandLine);
    if (status == FALSE)
        MessageBox(
            hWnd,
            "Cannot initialize the SQL engine", AppName,
            MB_OK | MB_ICONERROR);

    EnableWindow(hWnd, TRUE);

    return status;
}

int ShutdownEngine(HWND hWnd) {

    EnableWindow(hWnd, FALSE);

    int status = SirSQL_Stop(hWnd);
    if (status == FALSE)
        MessageBox(
            hWnd,
            "Cannot shutdown the SQL engine correctly", AppName,
            MB_OK | MB_ICONERROR);

    EnableWindow(hWnd, TRUE);

    return status;
}

int Execute(HWND hWnd, const char *command) {

    EnableWindow(hWnd, FALSE);

    SetCursor(LoadCursor(NULL, IDC_WAIT));

    int status = SirSQL_Exec(hWnd, command);
    if (status == FALSE)
        Beep(500, 100);

    SetCursor(LoadCursor(NULL, IDC_ARROW));

    EnableWindow(hWnd, TRUE);

    return status;
}

LRESULT MainWnd_OnCreate(HWND hWnd, char *CmdLine) {

    hFrame = hWnd;

    int dllVersion = SirSQL_VersionNumber();
    if (dllVersion < MinEngineVer) {
        char buffer[1024];
        sprintf(
            buffer,
            "Wrong dynamic link library\n\n"
            "The SQL engine from sirsql.dll version %d.%02d.%02d\n\n"
            "You must use SQL engine version %d.%02d.%02d or later",
            dllVersion/10000, dllVersion/100%100, dllVersion%100,
            MinEngineVer/10000, MinEngineVer/100%100, MinEngineVer%100);
        MessageBox(hWnd, buffer, AppName, MB_OK | MB_ICONERROR);
        return -1;
    }

    int fontSize = GetPrivateProfileInt(AppName, "FSize", 0, IniFile);
    HDC hDC = GetDC(hWnd);
    int fontHeight = -MulDiv(fontSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
    ReleaseDC(hWnd, hDC);
    hFont = CreateFont(
        fontHeight, 0, 0, 0, FW_BOLD, 0, 0, 0, ANSI_CHARSET,
        OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
        FIXED_PITCH, "Courier New");
    if (hFont == NULL)
        hFont = CreateFont(
            0, 0, 0, 0, FW_BOLD, 0, 0, 0, ANSI_CHARSET,
            OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
            FIXED_PITCH, "Courier New");

    InpWndRatio = GetPrivateProfileInt(AppName, "InpWndRatio", 30, IniFile);
    if (InpWndRatio < 15 || InpWndRatio > 75)
        InpWndRatio = 30;

    hInpWnd = CreateWindowEx(
        0, "EDIT", NULL,
        WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | WS_BORDER |
        ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL |
        ES_WANTRETURN,
        0, 0, 0, 0, hWnd, (HMENU)10030, hInst, NULL);
    if (hFont != NULL)
        SendMessage(hInpWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE,0));
    SendMessage(hInpWnd, EM_LIMITTEXT, 0, 0);

    hOutWnd = CreateWindowEx(
        0, "EDIT", NULL,
        WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | WS_BORDER |
        ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL |
        ES_NOHIDESEL | ES_READONLY,
        0, 0, 0, 0, hWnd, (HMENU)10031, hInst, NULL);
    if (hFont != NULL)
        SendMessage(hOutWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE,0));
    SendMessage(hOutWnd, EM_LIMITTEXT, 0, 0);

    AutoSave = GetPrivateProfileInt(AppName, "AutoSave", FALSE, IniFile);

    if (!InitEngine(hWnd, CmdLine))
        return -1;

    AddToOutputWindow("");
    AddToOutputWindow("Welcome to AcmeSQL interface!");
    AddToOutputWindow("This is a sample program for developers who plan to use SirAPI.");
    AddToOutputWindow("As a first step we advise you to read sirapi.h in api directory.");
    AddToOutputWindow("Should you wish to see some examples, the source code of AcmeSQL");
    AddToOutputWindow("is in examples subdirectory. Have a look at readme.txt first.");
    AddToOutputWindow("");

    return 0;
}

LRESULT MainWnd_OnClose(HWND hWnd) {

    if (AutoSave)
        Execute(hFrame, "SAVE");

    ShutdownEngine(hWnd);

    DestroyWindow(hWnd);

    if (hFont != NULL)
        DeleteObject(hFont);

    return 0;
}

LRESULT MainWnd_OnSize(HWND , int w, int h) {

    int InpWndH = h*InpWndRatio/100;
    int OutWndH = h-InpWndH;

    MoveWindow(hOutWnd, 0, 0      , w, OutWndH, TRUE);
    MoveWindow(hInpWnd, 0, OutWndH, w, InpWndH, TRUE);

    return 0;
}

LRESULT MainWnd_OnSetFocus(HWND) {
    SetFocus(hInpWnd);
    return 0;
}

LRESULT MainWnd_OnCommand(HWND hWnd, WORD cmd, WORD NCode, HWND hControl) {

    switch (cmd) {
        case CMD_EXECUTE: {
            char *cmd = GetInputText();
            if (cmd != NULL) {
                int len = strlen(cmd);
                int n = 0;
                for (int i = 0; i <= len; i++) {
                    if (cmd[i] == '\r') {
                        n++;
                    } else {
                        if (n != 0) {
                            cmd[i-n] = cmd[i];
                        }
                    }
                }
                if (Execute(hFrame, cmd))
                    SetInputText("");
                SetFocus(hInpWnd);
                delete cmd;
            }
            break;
        }
        case CMD_EXIT:
            SendMessage(hWnd, WM_CLOSE, 0, 0);
            break;
        default: ;
    }

    if (NCode == EN_MAXTEXT || NCode == EN_ERRSPACE) {
        Beep(500, 100);
        if (hControl == hOutWnd) {
            SetOutputText("");
        }
    }

    return 0;
}

LRESULT MainWnd_OnPaint(HWND hWnd) {
    HDC hDC;
    PAINTSTRUCT ps;
    hDC = BeginPaint(hWnd, &ps);
    EndPaint(hWnd, &ps);
    return 0;
}

LRESULT CALLBACK MainWnd_WndProc(
    HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam
) {
    typedef struct {
        short sz;
        void *p;
    } UNALIGNED *UP;

    switch (msg) {
        case WM_CREATE:
            return MainWnd_OnCreate(
                hWnd,
                (char *)((UP)(((LPCREATESTRUCT)lParam)->lpCreateParams))->p);
        case WM_CLOSE:
            return MainWnd_OnClose(hWnd);
        case WM_SIZE:
            return MainWnd_OnSize(hWnd, LOWORD(lParam), HIWORD(lParam));
        case WM_SETFOCUS:
            return MainWnd_OnSetFocus(hWnd);
        case WM_COMMAND:
            return MainWnd_OnCommand(
                hWnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
        case WM_PAINT:
            return MainWnd_OnPaint(hWnd);
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        default: return DefWindowProc(hWnd, msg, wParam, lParam);
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int) {

    hInst = hInstance;

    WNDCLASS wc;
    wc.style         = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
    wc.lpfnWndProc   = MainWnd_WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDR_MAINICON));
    wc.hCursor       = LoadCursor(0, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MAINMENU);
    wc.lpszClassName = "MainWnd";
    if (RegisterClass(&wc) == 0)
        return 0;

    struct {
        short sz;
        void *p;
    } CreateWindowParam = {sizeof(void *), lpCmdLine};

    HWND hWnd = CreateWindowEx(
        WS_EX_APPWINDOW,
        wc.lpszClassName, AppName,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        HWND_DESKTOP, NULL, hInstance, &CreateWindowParam);
    if (hWnd == NULL)
        return 0;

    ShowWindow(hWnd, SW_SHOWDEFAULT);

    HACCEL hAccel = LoadAccelerators(
        hInstance, MAKEINTRESOURCE(IDR_ACCELTABLE));

    MSG msg;
    while (GetMessage(&msg, 0, 0, 0) == TRUE) {
        if (!TranslateAccelerator(hWnd, hAccel, &msg)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    DestroyIcon(wc.hIcon);

    return msg.wParam;
}

SIRDBMSE

SIRDBMSE is a SIRDBMS console application which lets you enter DBMS commands and program and run them in a command window or telnet connection. Enter commands at the DBMS> prompt and run them by entering go. Enter exit to end the program. This program was written by Dave Doulton of the University of Southampton.

#include <string.h>
#include <stdio.h>
#include "sirapi.h"
void OutputHandler(const char *text) {
        if(text[0] == ' ')
        {
    printf("%s\n",text+1);
        }
        else
        {
    printf("%s\n",text);
        }
    
}

void DisplayHandler(const char *text) {
        if(text[0] == ' ')
        {
    printf("%s\n",text+1);
        }
        else
        {
    printf("%s\n",text);
        }
}


int main(int argc,char *argv[]) {
int  i;
int res;
char cmdLine[1024] = "";
char cmd[1024]= "";
char ocmd[1024]= "";
char line[200]="";
   for (i = 1; i < argc; i++) {
        if (i > 1) strcat(cmdLine, " ");
        strcat(cmdLine, argv[i]);
    }
    
    res=SirDBMS_Init((void *) 1, (void *) OutputHandler, (void *) DisplayHandler, cmdLine);
    if (res != 1)
    {
      res=SirDBMS_ErrorCode();
      printf("error code %ld\n",res);
    }
    printf("DBMS>");
    while (gets(line) != NULL) 
    {
        if(strcmp(line,"go") == 0)
        {
          res=SirDBMS_Exec((void *) 1,cmd);
          strcpy(ocmd,cmd);
          strcpy(cmd,"");
          printf("DBMS>");
        }
        else
        {
          if(strcmp(line,"rep") ==0)
          {
            res=SirDBMS_Exec((void *) 1,ocmd);
            strcpy(cmd,"");
            printf("DBMS>");
          }
          else
          {
            if(strcmp(line,"exit") ==0)
            {
              strcpy(cmd,"");
              break;
            }
            else
            {
              strcat(cmd,line);
          strcat(cmd,"\n");
              printf("DBMS>");
            }
          }
        }
    }
    res=SirDBMS_Exec((void *) 1,cmd);
    res=SirDBMS_Stop((void *) 1);
    return res;
}

homecontents start chapter top of pagebottom of pagenext page index

Compilation & Linkage

The header file (sirapi.h) and link library files (sirdbms.lib and sirsql.lib) are found in the API subdirectory of the SIR installation directory. These files must be used for compiling and linking the API program. Example makefiles for a couple of compilers are also included in this subdirectory.

To run a SIRAPI application the SIR dynamic libraries (eg. sirdbms.dll sirmdr.dll etc) must be in the application's directory or PATH.

homecontents start chapter top of pagebottom of pagenext page index