You might be interested in this:

* nconv.c - a modified uni-one-converter for inserting single MBOX file into 
DBMAIL as folder. [folder must exist]. Must be inside dbmail source folder in 
order to compile [sorry for bad C]. Must be called 

'nconv /home/user/mail/sent-mail 1 sent-mail'

* convert.pas - a program [must be compiled under Borland Kylix Open Edition], 
that traverse all the /var/spool/mail, and for each file in there
*** adds user to dbmail, 
*** set it's password from shadow file (call to dbmail-adduser), 
*** traverse /home/user/mail, adds mail folders for each file, 
*** and calls nconv for each file in /home/user/mail/

Those programs was not intendef for release, but may be useful for someone. I 
just wanted to convert my existing IMAP folders to DBMAIL. But if some C 
programmer hears me, all this could be done by uni-one-converter. i'm just not 
strong enough in C.

* LinuxUtils.pas and MyDB.pas additional libraries, required to compile 
convert.pas


Citēju Edward Allen <[EMAIL PROTECTED]>:

> I would like to create and maintain a web page for 3rd party dbmail 
> utilities and documentation.
> 
> If anyone is interested in posting stuff / helping out, please email me!
> 
> Thanks.
> 
> Edward Allen
> 
> 
> _______________________________________________
> Dbmail mailing list
> Dbmail@dbmail.org
> https://mailman.fastxs.nl/mailman/listinfo/dbmail
> 


-- 
Best regards,
Atis Lezdins aka xAM.
------------------------------------------------
"Do the simplest thing that could possibly work"
Kent Beck, father of eXtreme Programming.

/* 
 * this program traverses a directory tree and executes
 * dbmail conversion on each file.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <time.h>
#include <unistd.h>
#include "db.h"
#include "auth.h"
#include "dbmailtypes.h"
#include "debug.h"
#include <regex.h>

#define MAX_LINESIZE 1024
#define UID_SIZE 70

const char *mbox_delimiter_pattern = "^From .*  ";
char blk[READ_BLOCK_SIZE + MAX_LINESIZE + 1];

/* syslog */
#define PNAME "dbmail/uni-one-convertor"

/*char *getusername (char *path);*/
int traverse (char *fname, char *username, char *folder);
int process_mboxfile(char *file, u64_t userid, char *folder);



int main (int argc, char* argv[])
{
  time_t start;
  time_t stop;
  int result;

  if (argc != 4)
    {
      printf ("Programm syntax: nconv filename username folder\n\n");
      printf ("filename - name of file You want to convert\n");
      printf ("username - UserID\n");
      printf ("folder - Mailbox folder \n");
      return -1;
    }

  openlog(PNAME, LOG_PID, LOG_MAIL);   /* open connection to syslog */
  configure_debug(TRACE_ERROR, 1, 0);

  /* open dbase connections */
  if (db_connect() != 0 || auth_connect() != 0)
    {
      printf("Error opening dbase connections\n");
      return -1;
    }


  time (&start); /* mark the starting time */
  result = traverse (argv[1], argv[2], argv[3]);
  time (&stop); /* mark the ending time */

  printf ("Conversion started @  %s", ctime(&start));
  printf ("Conversion finished @ %s", ctime(&stop));

  return result;
}



/*char *getusername (char *path)
{
  int i;
  char *tmp;
        
  i = strlen (path);
  tmp = path+i;
        
  while ( (tmp!=path) && (*tmp!='/'))
    tmp--;

  return tmp+1;
}
*/

int traverse (char *fname, char *username, char *folder)
{
  char newpath [1024];
//  char *username;
  struct dirent **namelist;
  int n;
  u64_t userid;


  userid=strtoul (username, 0, 0);
//  n = scandir (path, &namelist, 0, alphasort);

//  if (n < 0)
//    {
//      printf ("file %s\n",path);
//      username = getusername(path);
//      printf ("username %s\n", username);
//         
//      printf("creating user...");
//      userid = auth_adduser(username, "default", "", "0", "0");
//      if (userid != -1 && userid != 0)
//      {
          printf("Ok id [%llu]\n", userid);
          printf("converting mailbox...");
          fflush(stdout);
          n = process_mboxfile(fname, userid, folder);
          if (n != 0)
            printf("Warning: error converting mailbox\n");
          else
            printf ("done :)\n");
//      }  
//      else
//      {
//        printf("user already exists. Skipping\n");
//      }
///     
/*    }
  else
    {
      while (n--)
        {
          if ((strcmp(namelist[n]->d_name,"..")!=0) &&
              (strcmp(namelist[n]->d_name,".")!=0))
            {
              sprintf (newpath,"%s/%s",path, namelist[n]->d_name);
              traverse (newpath);
            }
          free (namelist[n]);
        }
      free(namelist);
    }
*/
  return 0;
}


int process_mboxfile(char *file, u64_t userid, char *folder)
{
  regex_t preg;
  int result;
  FILE *infile;
  int in_msg, header_passed;
  char newunique[UID_SIZE];
  unsigned cnt,len,newlines;
  u64_t msgid=0, size;
  char saved;

  if ((result = regcomp(&preg, mbox_delimiter_pattern, REG_NOSUB)) != 0)
    {
      trace(TRACE_ERROR,"Regex compilation failed.");
      return -1;
    }

  if ( (infile = fopen(file, "r")) == 0)
    {
      
      trace(TRACE_ERROR,"Could not open file [%s]", infile);
      return -1;
    }

  in_msg = 0;
  cnt = 0;
  size = 0;
  newlines = 0;

  while (!feof(infile) && !ferror(infile))
    {
      if (fgets(&blk[cnt], MAX_LINESIZE, infile) == 0)
        break;

      /* check if this is an mbox delimiter */
      if (regexec(&preg, &blk[cnt], 0, NULL, 0) == 0)
        {
          if (!in_msg)
            in_msg = 1; /* ok start of a new msg */
          else
            {
              /* update & end message */
              db_insert_message_block(blk, cnt, msgid);

              snprintf(newunique, UID_SIZE, "%lluA%lu", userid, time(NULL));
              db_update_message(msgid, newunique, size+cnt, size+cnt+newlines);
              trace(TRACE_ERROR, "message [%llu] inserted, [%u] bytes", msgid, 
size+cnt);
            }

          /* start new message */
          /* should be red as db_insert_message(userid,"INBOX",0); */
          printf(folder);
          msgid = db_insert_message(userid, folder, 0);
          header_passed = 0;
          cnt = 0;
          size = 0;
          newlines = 0;
        }
      else
        {
          newlines++;
          if (header_passed == 0)
            {
              /* we're still reading the header */
              len = strlen(&blk[cnt]);
              if (strcmp(&blk[cnt], "\n") == 0)
                {
                  db_insert_message_block(blk, cnt+len, msgid);
                  header_passed = 1;
                  size += (cnt+len);
                  cnt = 0;
                }
              else
                cnt += len;
            }
          else
            {
              /* this is body data */
              len = strlen(&blk[cnt]);
              cnt += len;
              
              if (cnt >= READ_BLOCK_SIZE)
                {
                  /* write block */
                  saved = blk[READ_BLOCK_SIZE];

                  blk[READ_BLOCK_SIZE] = '\0';
                  db_insert_message_block(blk, READ_BLOCK_SIZE, msgid);
                  blk[READ_BLOCK_SIZE] = saved;

                  memmove(blk, &blk[READ_BLOCK_SIZE], cnt - (READ_BLOCK_SIZE));
                  size += READ_BLOCK_SIZE;
                  cnt  -= READ_BLOCK_SIZE;
                }
            }
        }
    }

  /* update & end message */
  if (msgid > 0)
    {
      db_insert_message_block(blk, cnt, msgid);

      snprintf(newunique, UID_SIZE, "%lluA%lu", userid, time(NULL));
      db_update_message(msgid, newunique, size+cnt, size+cnt+newlines);
      trace(TRACE_ERROR, "message [%llu] inserted, [%u] bytes", msgid, 
size+cnt);
    }

  fclose(infile);
  return 0;
}
program convert;

uses Libc, SysUtils, MyDB, LinuxUtils;

var My: TMyDB;
    DirHandle: PDirectoryStream;
    FileEnt: PDirEnt;
    CurrFile: string;
    CurrUser: string;
    UserID: string;
    Pipe: TPipe;

function CreateFolder(Folder: string): string;
begin
  while Folder[1]='/' do delete(Folder,1,1);
  Write('Creating folder '+Folder+' : ');
  My.Query('INSERT INTO mailboxes SET owner_idnr='+UserID+', name="'+Folder+'", 
permission=2');
  My.Query('SELECT mailbox_idnr FROM mailboxes WHERE owner_idnr='+UserID+' AND 
name="'+Folder+'"');
  Result:=My.ResultSet[0][0];
  WriteLn('Ok');
  WriteLn('Folder ID: '+Result);
end;

procedure ImportFolder(const Folder: string; FileName: string);
var FolderID: string;
    Pipe: TPipe;
    S: string;
begin
  S:=Folder;
  while S[1]='/' do delete(S,1,1);

  FolderID:=CreateFolder(S);

  WriteLn('Importing folder '+S+' from '+FileName+' : ');
  WriteLn('Executing ./nconv '+FileName+' '+UserID+' '+S);
  
  Pipe:=TPipe.Create('./nconv '+FileName+' '+UserID+' '+S,PipeRead);
  while not Pipe.Eof do begin
    Pipe.ReadLn(S);
    WriteLn('nconvert:> '+S);
  end;
  Pipe.Free;
  WriteLn('Importing folder: Ok');
end;

procedure ProcessDir(Dir: string; Prefix: string);
var
    LocalDirHandle: PDirectoryStream;
    LocalFileEnt: PDirEnt;
    LocalFile: string;
    ThisPrefix: string;
begin
  WriteLn('Processing '+Dir);
  LocalDirHandle:=OpenDir(PChar(Dir));
  if LocalDirHandle=nil then exit;
  repeat
    LocalFileEnt:=ReadDir(LocalDirHandle);
    if LocalFileEnt=nil then break;
    LocalFile:=StrPas(LocalFileEnt.d_name);
    if LocalFile='.' then continue;
    if LocalFile='..' then continue;
    ThisPrefix:=Prefix+'/'+LocalFile;
    if LocalFileEnt.d_type=4 then begin
      { It's a sub-dir, process it too }
      CreateFolder(ThisPrefix);
      ProcessDir(Dir+LocalFile+'/',ThisPrefix);
    end else if LocalFileEnt.d_type=8 then begin
      ImportFolder(ThisPrefix, Dir+LocalFile);
    end;
  until false;
  CloseDir(LocalDirHandle);
end;

begin
  My:=TMyDb.Create(nil);
  My.Host:='localhost';
  My.User:='dbmail';
  My.Password:='dbma1l';
  My.Database:='dbmail';
  My.Port:=3306;
  My.Active:=true;
  

  DirHandle:=OpenDir('/var/spool/mail');

  repeat
    FileEnt:=ReadDir(DirHandle);
    if FileEnt=nil then break;
    CurrFile:=StrPas(FileEnt.d_name);
    if CurrFile='.' then continue;
    if CurrFile='..' then continue;
    if copy(CurrFile,1,6)='BOGUS.' then continue;

//    if CurrFile<>'atis.l' then continue;
    
    CurrUser:=CurrFile;
    WriteLn('--------------------------------------');
    Write('Adding user '+CurrUser+': ');
    { create user }
    My.Query('INSERT INTO users SET userid="'+CurrUser+'"');
    WriteLn('Ok');
    
    Write('Getting userid: ');
    My.Query('SELECT user_idnr FROM users WHERE userid="'+CurrUser+'"');
    UserID:=My.ResultSet[0][0];
    WriteLn(UserID);
    
    
    Write('Applying shadow password: ');
    Pipe:=TPipe.Create('/stuff/dbmail/dbmail/dbmail-adduser c '+CurrUser+' 
-P:shadow', PipeRead);
    while not Pipe.Eof do Pipe.ReadLn();
    Pipe.Free;
    WriteLn('Ok');
    
    { do inbox import }
    ImportFolder('INBOX','/var/spool/mail/'+CurrFile);
    
    CreateFolder('mail');
    ProcessDir('/home/'+CurrUser+'/mail/','/');


  until false;
  CloseDir(DirHandle);
    

  

end.
unit LinuxUtils;

interface

uses Libc;

type TPipeIOMode = (PipeRead, PipeWrite);

type TPipe=class
        private
          FHandle: PIOFile;
          pPipeStr: pointer;
          Data: string;
          FEof: boolean;
          procedure GetLine();
        public
          property Eof: boolean read FEof;
          constructor Create(Command: string;  Mode: TPipeIOMode);
          destructor Destroy(); override;
          procedure ReadLn(var Line: string); overload;
          function ReadLn(): string; overload;
          procedure WriteLn(Line: string);
     end;

procedure KrnlRandom(var R: char); overload;
procedure KrnlRandom(var S: string; len: longword); overload;
procedure KrnlRandom(var R: shortint); overload;
procedure KrnlRandom(var R: smallint); overload;
procedure KrnlRandom(var R: integer); overload;
procedure KrnlRandom(var R: int64); overload;
        
implementation

function __KrnlRandom(): byte; 
var RndFile: TextFile; 
  R: Char; 
begin 
  AssignFile(RndFile,'/dev/urandom'); 
  Reset(RndFile); 
  Read(RndFile,R); 
  CloseFile(RndFile); 
  Result:=Ord(R); 
end; 

procedure KrnlRandom(var R: char); overload;
begin
  R:=Chr(__KrnlRandom);
end;

procedure KrnlRandom(var S: string; len: longword); overload;
var i: longword;
    C: char;
begin
  S:='';
  for i:=1 to len do begin
    KrnlRandom(C);
    S:=S+C;
  end;
end;

procedure KrnlRandom(var R: shortint); overload;
begin
  R:=__KrnlRandom;
end;

procedure KrnlRandom(var R: smallint); overload;
begin
  R:=(__KrnlRandom * $FF) + __KrnlRandom;
end;

procedure KrnlRandom(var R: integer); overload;
begin
  R:=(__KrnlRandom * $FFFFFF) + (__KrnlRandom * $FFFF) + (__KrnlRandom * $FF) + 
__KrnlRandom;
end;

procedure KrnlRandom(var R: int64); overload;
begin
  R:= (__KrnlRandom * $FFFFFFFFFFFFFF) + (__KrnlRandom * $FFFFFFFFFFFF) + 
(__KrnlRandom * $FFFFFFFFFF) + (__KrnlRandom * $FFFFFF) + (__KrnlRandom * 
$FFFF) + (__KrnlRandom * $FF) + __KrnlRandom;
end;

constructor TPipe.Create(Command: string; Mode: TPipeIOMode);
var Access: Pchar;
begin
  Access:='w';
  if Mode=PipeRead then Access:='r';
  FHandle:=popen(PChar(Command),Access);
  if assigned(FHandle) then FEof:=false;
  if Access='r' then begin
    GetLine;
  end;
end;

destructor TPipe.Destroy();
begin
  pclose(FHandle);
end;

procedure TPipe.GetLine();
var 
  P: longint;
begin
  if not assigned (FHandle) then begin
    Data:='';
    FEof:=true;
    exit;
  end;
  SetLength(Data,1024);
  pPipeStr:=fgets(@Data[1],1024,FHandle);
  if not assigned (pPipeStr) then begin
    Data:='';
    FEof:=true;
    exit;
  end;
  P:=Pos(#0,Data);
  if P=0 then begin
    Data:='';
    FEof:=true;
    Exit;
  end;
  Delete(Data,P-1,1024);
end;

procedure TPipe.ReadLn(var Line: string);
begin
  Line:=Data;
  GetLine;
end;

function TPipe.ReadLn(): string;
begin
  Result:=Data;
  GetLine;
end;

procedure TPipe.WriteLn(Line: string);
begin
  fputs(PChar(Line+^J),FHandle);
end;

begin

end.
unit MyDB;
interface
uses {$IFNDEF LINUX}Windows, {$ENDIF}Classes, SysUtils;

// Most important thing to check if functionality fails,
// check these compiler switches:

{$IFDEF LINUX}
{$DEFINE NEW_LIBMYSQL_DLL}
// $ DEFINE OLD_LIBMYSQL_DLL
{$ENDIF}


//i'm developing on Linux Redhat 7.1 with
//custom installation of MySQL 3.23 client+server,
//typically i need the new libs.
//Obviously there's no way to check library version before compiling :(

////////////////////////////////////////////////
//                                            //
// TMyDB component v 0.1 by [EMAIL PROTECTED] //
// TMyDB is a MySQL specific interface        //
//                                            //
////////////////////////////////////////////////

// MySQL stand-alone interface unit & component
// Developed with Kylix OE,
// should work on delphi 4 and higher as well
// By [EMAIL PROTECTED]
//
// * For both component and low level use.
// * Most relevant functions ported.
// * Special functionality to get results in
//   two-dimensional array (type TQueryResult)
// * design time functionality

// Got some header stripped from Zeos components.
// Their header is below. Tx pals.
//
// Zeos left some compiler switches which
// may or may not be relevant for your windows/linux system
//
// { $ DEFINE OLD_LIBMYSQL_DLL}
// { $ DEFINE NEW_LIBMYSQL_DLL}
//
// ToDo:
// *Debug this unit!
// *set options for real_connect, like compression etc.

//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

{********************************************************}
{                                                        }
{                 Zeos Database Objects                  }
{        Delphi plain interface to libmysql.dll          }
{                                                        }
{       Copyright (c) 1999-2001 Sergey Seroukhov         }
{    Copyright (c) 1999-2001 Zeos Development Group      }
{                                                        }
{********************************************************}


{***************** Plain API Constants definition ****************}

const
{$IFNDEF LINUX}
  DEFAULT_DLL_LOCATION = 'libmysql.dll';
{$ELSE}
  DEFAULT_DLL_LOCATION = '/usr/lib/mysql/libmysqlclient.so';
{$ENDIF}

{General Declarations}
  MYSQL_ERRMSG_SIZE    = 200;
  MYSQL_PORT           = 3306;
  LOCAL_HOST           = 'localhost';
  NAME_LEN             = 64;
  PROTOCOL_VERSION     = 10;
  FRM_VER              = 6;

{Enum Field Types}
  FIELD_TYPE_DECIMAL   = 0;
  FIELD_TYPE_TINY      = 1;
  FIELD_TYPE_SHORT     = 2;
  FIELD_TYPE_LONG      = 3;
  FIELD_TYPE_FLOAT     = 4;
  FIELD_TYPE_DOUBLE    = 5;
  FIELD_TYPE_NULL      = 6;
  FIELD_TYPE_TIMESTAMP = 7;
  FIELD_TYPE_LONGLONG  = 8;
  FIELD_TYPE_INT24     = 9;
  FIELD_TYPE_DATE      = 10;
  FIELD_TYPE_TIME      = 11;
  FIELD_TYPE_DATETIME  = 12;
  FIELD_TYPE_YEAR      = 13;
  FIELD_TYPE_NEWDATE   = 14;
  FIELD_TYPE_ENUM      = 247;
  FIELD_TYPE_SET       = 248;
  FIELD_TYPE_TINY_BLOB = 249;
  FIELD_TYPE_MEDIUM_BLOB = 250;
  FIELD_TYPE_LONG_BLOB = 251;
  FIELD_TYPE_BLOB      = 252;
  FIELD_TYPE_VAR_STRING = 253;
  FIELD_TYPE_STRING    = 254;

{For Compatibility}
  FIELD_TYPE_CHAR      = FIELD_TYPE_TINY;
  FIELD_TYPE_INTERVAL  = FIELD_TYPE_ENUM;

{ Field's flags }
  NOT_NULL_FLAG          = 1;     { Field can't be NULL }
  PRI_KEY_FLAG           = 2;     { Field is part of a primary key }
  UNIQUE_KEY_FLAG        = 4;     { Field is part of a unique key }
  MULTIPLE_KEY_FLAG      = 8;     { Field is part of a key }
  BLOB_FLAG              = 16;    { Field is a blob }
  UNSIGNED_FLAG          = 32;    { Field is unsigned }
  ZEROFILL_FLAG          = 64;    { Field is zerofill }
  BINARY_FLAG            = 128;   { Field is binary }
  ENUM_FLAG              = 256;   { Field is an enum }
  AUTO_INCREMENT_FLAG    = 512;   { Field is a autoincrement field }
  TIMESTAMP_FLAG         = 1024;  { Field is a timestamp }
  SET_FLAG               = 2048;  { Field is a set }
  NUM_FLAG               = 32768; { Field is num (for clients) }

{Server Administration Refresh Options}
  REFRESH_GRANT          = 1;     { Refresh grant tables }
  REFRESH_LOG            = 2;     { Start on new log file }
  REFRESH_TABLES         = 4;     { close all tables }
  REFRESH_HOSTS          = 8;     { Flush host cache }
  REFRESH_STATUS         = 16;    { Flush status variables }
  REFRESH_THREADS        = 32;    { Flush status variables }
  REFRESH_SLAVE          = 64;    { Reset master info abd restat slave thread }
  REFRESH_MASTER         = 128;   { Remove all bin logs in the index and 
truncate the index }
  REFRESH_READ_LOCK      = 16384; { Lock tables for read }
  REFRESH_FAST           = 32768; { Intern flag }

{ Client Connection Options }
  _CLIENT_LONG_PASSWORD   = 1;    { new more secure passwords }
  _CLIENT_FOUND_ROWS      = 2;    { Found instead of affected rows }
  _CLIENT_LONG_FLAG       = 4;    { Get all column flags }
  _CLIENT_CONNECT_WITH_DB = 8;    { One can specify db on connect }
  _CLIENT_NO_SCHEMA       = 16;   { Don't allow database.table.column }
  _CLIENT_COMPRESS        = 32;   { Can use compression protcol }
  _CLIENT_ODBC            = 64;   { Odbc client }
  _CLIENT_LOCAL_FILES     = 128;  { Can use LOAD DATA LOCAL }
  _CLIENT_IGNORE_SPACE    = 256;  { Ignore spaces before '(' }
  _CLIENT_CHANGE_USER     = 512;  { Support the mysql_change_user() }
  _CLIENT_INTERACTIVE     = 1024; { This is an interactive client }
  _CLIENT_SSL             = 2048; { Switch to SSL after handshake }
  _CLIENT_IGNORE_SIGPIPE  = 4096; { IGNORE sigpipes }
  _CLIENT_TRANSACTIONS    = 8196; { Client knows about transactions }


{****************** Plain API Types definition *****************}

type
   TBOOL =LongBool;
   TInt64=Int64;
  TClientCapabilities = (
    CLIENT_LONG_PASSWORD,
    CLIENT_FOUND_ROWS,
    CLIENT_LONG_FLAG,
    CLIENT_CONNECT_WITH_DB,
    CLIENT_NO_SCHEMA,
    CLIENT_COMPRESS,
    CLIENT_ODBC,
    CLIENT_LOCAL_FILES,
    CLIENT_IGNORE_SPACE
  );

  TSetClientCapabilities = set of TClientCapabilities;

  TRefreshOptions = (
    _REFRESH_GRANT,
    _REFRESH_LOG,
    _REFRESH_TABLES,
    _REFRESH_HOSTS,
    _REFRESH_FAST
  );
  TSetRefreshOptions = set of TRefreshOptions;

  mysql_status = (
    MYSQL_STATUS_READY,
    MYSQL_STATUS_GET_RESULT,
    MYSQL_STATUS_USE_RESULT
  );

  mysql_option = (
    MYSQL_OPT_CONNECT_TIMEOUT,
    MYSQL_OPT_COMPRESS,
    MYSQL_OPT_NAMED_PIPE,
    MYSQL_INIT_COMMAND,
    MYSQL_READ_DEFAULT_FILE,
    MYSQL_READ_DEFAULT_GROUP,
    MYSQL_SET_CHARSET_DIR,
    MYSQL_SET_CHARSET_NAME
  );

  PUSED_MEM=^USED_MEM;
  USED_MEM = packed record
    next:       PUSED_MEM;
    left:       Integer;
    size:       Integer;
  end;

  PERR_PROC = ^ERR_PROC;
  ERR_PROC = procedure;

  PMEM_ROOT = ^MEM_ROOT;
  MEM_ROOT = packed record
    free:          PUSED_MEM;
    used:          PUSED_MEM;
{$IFDEF NEW_LIBMYSQL_DLL}
    pre_alloc:     PUSED_MEM;
{$ENDIF}
    min_malloc:    Integer;
    block_size:    Integer;
    error_handler: PERR_PROC;
  end;

  NET = packed record
    vio:           Pointer;
    fd:            Integer;
    fcntl:         Integer;
    buff:          PChar;
    buff_end:      PChar;
    write_pos:     PChar;
    read_pos:      PChar;
    last_error:    array[01..MYSQL_ERRMSG_SIZE] of Char;
    last_errno:    Integer;
    max_packet:    Integer;
    timeout:       Integer;
    pkt_nr:        Integer;
{$IFDEF NEW_LIBMYSQL_DLL}
    error:         Char;
{$ELSE}
    error:         TBool;
{$ENDIF}
    return_errno:  TBool;
    compress:      TBool;
{$IFDEF NEW_LIBMYSQL_DLL}
    no_send_ok:    TBool;
{$ENDIF}
    remain_in_buf: LongInt;
    length:        LongInt;
    buf_length:    LongInt;
    where_b:       LongInt;
{$IFDEF NEW_LIBMYSQL_DLL}
    return_status: Pointer;
    reading_or_writing: Char;
{$ELSE}
    more:          TBool;
{$ENDIF}
    save_char:     Char;
  end;

  MYSQL_FIELD = record
    name:       PChar;
    table:      PChar;
    def:        PChar;
    _type:      Byte;
    length:     Integer;
    max_length: Integer;
    flags:      Integer;
    decimals:   Integer;
  end;

  PMYSQL_FIELD = ^MYSQL_FIELD;
  MYSQL_FIELDS = array [0..$ff] of MYSQL_FIELD;
  PMYSQL_FIELDS = ^MYSQL_FIELDS;

  MYSQL_FIELD_OFFSET = Cardinal;

  MYSQL_ROW = array[00..$ff] of PChar;
  PMYSQL_ROW = ^MYSQL_ROW;

  PMYSQL_ROWS = ^MYSQL_ROWS;
  MYSQL_ROWS = record
    next:       PMYSQL_ROWS;
    data:       PMYSQL_ROW;
  end;

  MYSQL_ROW_OFFSET = PMYSQL_ROWS;

  MYSQL_DATA = record
    Rows:       TInt64;
    Fields:     Cardinal;
    Data:       PMYSQL_ROWS;
    Alloc:      MEM_ROOT;
  end;
  PMYSQL_DATA = ^MYSQL_DATA;

type
  _MYSQL_OPTIONS = record
    connect_timeout: Integer;
    clientFlag:      Integer;
    compress:        TBool;
    named_pipe:      TBool;
    port:            Integer;
    host:            PChar;
    init_command:    PChar;
    user:            PChar;
    password:        PChar;
    unix_socket:     PChar;
    db:              PChar;
    my_cnf_file:     PChar;
    my_cnf_group:    PChar;
    charset_dir:     PChar;
    charset_name:    PChar;
    use_ssl:         TBool;
    ssl_key:         PChar;
    ssl_cert:        PChar;
    ssl_ca:          PChar;
    ssl_capath:      PChar;
  end;
  PMYSQL_OPTIONS = ^_MYSQL_OPTIONS;

  MYSQL = record
    _net:            NET;
    connector_fd:    PChar;
    host:            PChar;
    user:            PChar;
    passwd:          PChar;
    unix_socket:     PChar;
    server_version:  PChar;
    host_info:       PChar;
    info:            PChar;
    db:              PChar;
    port:            Integer;
    client_flag:     Integer;
    server_capabilities: Integer;
    protocol_version: Integer;
    field_count:     Integer;
{$IFDEF NEW_LIBMYSQL_DLL}
    server_status:   Integer;
{$ENDIF}
    thread_id:       LongInt;
    affected_rows:   TInt64;
    insert_id:       TInt64;
    extra_info:      TInt64;
    packet_length:   LongInt;
    status:          mysql_status;
    fields:          PMYSQL_FIELD;
    field_alloc:     MEM_ROOT;
    free_me, reconnect: TBool;
    options:         _mysql_options;
    scramble_buff:   array[0..8] of Char;
    charset:         PChar;
{$IFDEF NEW_LIBMYSQL_DLL}
    server_language: Integer;
{$ENDIF}
  end;
  PMYSQL = ^MYSQL;

  MYSQL_RES = packed record
    row_count:       TInt64;
    field_count:     Integer;
    current_field:   Integer;
    fields:          PMYSQL_FIELD;
    data:            PMYSQL_DATA;
    data_cursor:     PMYSQL_ROWS;
    field_alloc:     MEM_ROOT;
    row:             PMYSQL_ROW;
    current_row:     PMYSQL_ROW;
    lengths:         PLongInt;
    handle:          PMYSQL;
    eof:             TBool;
  end;
  PMYSQL_RES = ^MYSQL_RES;

  TModifyType = (MODIFY_INSERT, MODIFY_UPDATE, MODIFY_DELETE);
  TQuoteOptions = (QUOTE_STRIP_CR,QUOTE_STRIP_LF);
  TQuoteOptionsSet = set of TQuoteOptions;

{************** Plain API Function types definition *************}

  Tmysql_debug = procedure(Debug: PChar);

  Tmysql_dump_debug_info = function(Handle: PMYSQL): Integer;

  Tmysql_init = function(Handle: PMYSQL): PMYSQL;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_connect = function(Handle: PMYSQL; const Host, User, Passwd: PChar):
    PMYSQL; {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_real_connect = function(Handle: PMYSQL;
    const Host, User, Passwd, Db: PChar; Port: Cardinal;
    unix_socket: PChar; clientflag: Cardinal): PMYSQL;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_close = procedure(Handle: PMYSQL);
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_query = function(Handle: PMYSQL; const Query: PChar): Integer;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_real_query = function(Handle: PMYSQL; const Query: PChar;
    len: Integer): Integer;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_select_db = function(Handle: PMYSQL; const Db: PChar): Integer;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_create_db = function(Handle: PMYSQL; const Db: PChar): Integer;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_drop_db = function(Handle: PMYSQL; const Db: PChar): Integer;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_shutdown = function(Handle: PMYSQL): Integer;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_refresh = function(Handle: PMYSQL; Options: Cardinal): Integer;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_kill = function(Handle: PMYSQL; Pid: longint): Integer;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_ping = function(Handle: PMYSQL): Integer;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_stat = function(Handle: PMYSQL): PChar;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_options = function(Handle: PMYSQL; Option: mysql_option;
    const Arg: PChar): Integer; {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_escape_string = function(PTo, PFrom: PChar; Len: Cardinal): Cardinal;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_get_server_info = function(Handle: PMYSQL): PChar;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_get_client_info = function: PChar;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_get_host_info = function(Handle: PMYSQL): PChar;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_get_proto_info = function(Handle: PMYSQL): Cardinal;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_list_dbs = function(Handle: PMYSQL; Wild: PChar): PMYSQL_RES;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_list_tables = function(Handle: PMYSQL; const Wild: PChar): PMYSQL_RES;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_list_fields = function(Handle: PMYSQL; const Table, Wild: PChar):
    PMYSQL_RES; {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_list_processes = function(Handle: PMYSQL): PMYSQL_RES;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_store_result = function(Handle: PMYSQL): PMYSQL_RES;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_use_result = function(Handle: PMYSQL): PMYSQL_RES;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_free_result = procedure(Result: PMYSQL_RES);
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_fetch_row = function(Result: PMYSQL_RES): PMYSQL_ROW;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_fetch_lengths = function(Result: PMYSQL_RES): PLongInt;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_fetch_field = function(Result: PMYSQL_RES): PMYSQL_FIELD;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

{$IFNDEF OLD_LIBMYSQL_DLL}
  Tmysql_data_seek = procedure(Result: PMYSQL_RES; Offset: TInt64);
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};
{$ELSE}
  Tmysql_data_seek = procedure(Result: PMYSQL_RES; Offset: Cardinal);
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};
{$ENDIF}

  Tmysql_row_seek = function(Result: PMYSQL_RES; Row: MYSQL_ROW_OFFSET):
    MYSQL_ROW_OFFSET; {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_field_seek = function(Result: PMYSQL_RES; Offset: mysql_field_offset):
    mysql_field_offset; {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};

  Tmysql_thread_id = function(Handle: PMYSQL): cardinal;
    {$IFNDEF LINUX} stdcall {$ELSE} cdecl {$ENDIF};
  //EOZeos
  //Functions added by [EMAIL PROTECTED]:
  Tmysql_insert_id = function(Handle: PMYSQL):Int64;          {$IFNDEF LINUX} 
stdcall {$ELSE} cdecl {$ENDIF};
  Tmysql_fetch_fields = function(Result: PMYSQL_RES):PMYSQL_FIELDS; {$IFNDEF 
LINUX} stdcall {$ELSE} cdecl {$ENDIF};
  Tmysql_num_fields = function(Result: PMYSQL_RES):Integer;   {$IFNDEF LINUX} 
stdcall {$ELSE} cdecl {$ENDIF};
  //EOArTee

  //ZEOS:
{************* Plain API Function variables definition ************}

var
  mysql_debug:          Tmysql_debug;
  mysql_dump_debug_info: Tmysql_dump_debug_info;
  mysql_init:           Tmysql_init;
  mysql_connect:        Tmysql_connect;
  mysql_real_connect:   Tmysql_real_connect;
  mysql_close:          Tmysql_close;
  mysql_select_db:      Tmysql_select_db;
  mysql_create_db:      Tmysql_create_db;
  mysql_drop_db:        Tmysql_drop_db;
  mysql_query:          Tmysql_query;
  mysql_real_query:     Tmysql_query;
  mysql_shutdown:       Tmysql_shutdown;
  mysql_refresh:        Tmysql_refresh;
  mysql_kill:           Tmysql_kill;
  mysql_ping:           Tmysql_ping;
  mysql_stat:           Tmysql_stat;
  mysql_options:        Tmysql_options;
  mysql_escape_string:  Tmysql_escape_string;
  mysql_get_server_info: Tmysql_get_server_info;
  mysql_get_client_info: Tmysql_get_client_info;
  mysql_get_host_info:  Tmysql_get_host_info;
  mysql_get_proto_info: Tmysql_get_proto_info;
  mysql_list_dbs:       Tmysql_list_dbs;
  mysql_list_tables:    Tmysql_list_tables;
  mysql_list_fields:    Tmysql_list_fields;
  mysql_list_processes: Tmysql_list_processes;
  mysql_data_seek:      Tmysql_data_seek;
  mysql_row_seek:       Tmysql_row_seek;
  mysql_field_seek:     Tmysql_field_seek;
  mysql_fetch_row:      Tmysql_fetch_row;
  mysql_fetch_lengths:  Tmysql_fetch_lengths;
  mysql_fetch_field:    Tmysql_fetch_field;
  mysql_store_result:   Tmysql_store_result;
  mysql_use_result:     Tmysql_use_result;
  mysql_free_result:    Tmysql_free_result;
  mysql_thread_id:      Tmysql_thread_id;
  //EOZEOS
  //ArTee:
  mysql_insert_id:      Tmysql_insert_id;
  mysql_fetch_fields:   Tmysql_fetch_fields;
  mysql_num_fields:     Tmysql_num_fields;
  //EOArTEe

//ZEOS:
function MySqlLoadLib: Boolean;

var
     DLL: string = DEFAULT_DLL_LOCATION;

var  hDLL: THandle = 0;
     LibLoaded: Boolean = False;
//EOZEOS

//TMyDB Component definition by ArTee:

const MY_DEFAULT_PORT=3306;

type TQueryRow=Array of String;
     TQueryResult=Array of TQueryRow;
     TExtResult= record IsNull:Boolean;
                 end;
     TExtQueryRow = Array of TExtResult;
     TExtQueryResult = Array of TExtQueryRow;

     //Some types redefined
     //Mainly PChar to String conversion:

     TMySQLField = record
                     name,
                     table,
                     def: String;
                     _type: Byte;
                     length: Integer;
                     max_length: Integer;
                     flags: Integer;
                     decimals: Integer;
                   end;
     TMySQLFields = array of TMySQLField;

     TMyDB = class (TComponent)
     private
       MyHandle:MySQL;
       PMyHandle:PMySQL;
       FActive:Boolean;
       FHost:String;
       FPort:Integer;
       FUser:String;
       FPass:String;
       FDatabase:String;
       FLibrary:String;
       FSQL:String;
       FLastError:String;
       FHasResult:Boolean;
       FQueryResult:TQueryResult;
       FExtQueryResult:TExtQueryResult;
       FLastInsertID:Int64;
       FRowsAffected:Integer;
       FResultFields:TStringList;
       FResultTable:String;
       FResultAsString:String;
       FResultAsText:String;
       FResultAsHTML:String;
       FFieldNames:TStrings;
       FFields:TMySQLFields;
       FNumFields:Integer;
       FFetchRowLimit:Integer;
       FFetchMemoryLimit:Integer;
       FCharSet:String;
       FServerVersion:String;
       FHostInfo:String;
       FInfo:String;
       FRealConnect:Boolean;
       FUnixSock:String;
       FConnectOptions:Integer;
       ActivateOnLoad:Boolean;
       FOnError:TNotifyEvent;
       FOnBeforeQuery:TNotifyEvent;
       FOnSuccess:TNotifyEvent;
       FOnOpen:TNotifyEvent;
       FOnClose:TNotifyEvent;
       procedure StoreResult(Res: PMYSQL_RES);
     protected
       procedure Loaded; override;
     public
       procedure SetActive (DBActive:Boolean);
       Constructor Create (AOwner:TComponent); override;
       procedure Connect (Host, User, Pass:String);
       procedure Close;
       procedure Query (SQL:String);
       procedure SelectDatabase(Database:String);
       procedure CreateDatabase(Database:String);
       procedure DropDatabase(Database:String);
       procedure ListDatabases(wildcard:String='');
       procedure ListTables(wildcard:String='');
       procedure ListFields(table:String; wildcard:String='');
       procedure ListProcesses;
       procedure ShutDown;
       procedure Kill (Pid:Integer);
       procedure SetPort (Port:Integer);
       procedure SetRealConnect(DoRealConnect:Boolean);
       function Ping:Boolean;
       function GetLastError:String;
       function GetServerInfo:String;
       property LastInsertID:Int64 read FLastInsertID;
       property RowsAffected:Integer read FRowsAffected;
       property ResultFields:TStringList read FResultFields;
       property ResultTable:String read FResultTable;
       property DBHandle:MySQL read MyHandle;
       property HasResult:Boolean read FHasResult write FHasResult;
       property LastError:String read FLastError;
       property ResultSet:TQueryResult read FQueryResult;
       property ExtResultSet:TExtQueryResult read FExtQueryResult;
       property ServerInfo:String read GetServerInfo;
       property FieldNames:TStrings read FFieldNames;
       property Fields:TMySQLFields read FFields;
       property ResultAsString:String read FResultAsString;
       property ResultAsText:String read FResultAsText;
       property NumFields:Integer read FNumFields;
       property CharSet:String read FCharSet;
       property ServerVersion:String read FServerVersion;
       property Info:String read FInfo;
       property HostInfo:String read FHostInfo;
       property UnixSock:String read FUnixSock write FUnixSock;
     published
       property SQL:String read FSQL write FSQL;
       property Active:Boolean read FActive write SetActive;
       property Host:String read FHost write FHost;
       property Port:Integer read FPort write SetPort;
       property Database:String read FDatabase write SelectDatabase;
       property SharedLibrary:String read FLibrary write FLibrary;
       property User:String read FUser write FUser;
       property Password:String read FPass write FPass;
       property FetchRowLimit:Integer read FFetchRowLimit write FFetchRowLimit 
default 0;
       property FetchMemoryLimit:Integer read FFetchMemoryLimit write 
FFetchMemoryLimit default 2*1024*1024; //2Mb       //Events:
       property RealConnect:Boolean read FRealConnect write SetRealConnect;
       property OnError:TNotifyEvent read FOnError write FOnError;
       property OnBeforeQuery:TNotifyEvent read FOnBeforeQuery write 
FOnBeforeQuery;
       property OnOpen:TNotifyEvent read FOnOpen write FOnOpen;
       property OnClose:TNotifyEvent read FOnClose write FOnClose;
       property OnSuccess:TNotifyEvent read FOnSuccess write FOnSuccess;
     end;

procedure Register;

implementation


// Initialize MySQL dynamic library
function MySqlLoadLib: Boolean;
begin
  if hDLL = 0 then
  begin
    hDLL := GetModuleHandle(PChar(DLL));
    LibLoaded := False;
    if hDLL = 0 then
    begin
      hDLL := LoadLibrary(PChar(DLL));
      LibLoaded := True;
    end;
  end;

  if hDLL <> 0 then begin
    @mysql_debug           := GetProcAddress(hDLL,'mysql_debug');
    @mysql_dump_debug_info := GetProcAddress(hDLL,'mysql_dump_debug_info');
    @mysql_init            := GetProcAddress(hDLL,'mysql_init');
    @mysql_connect         := GetProcAddress(hDLL,'mysql_connect');
    @mysql_real_connect    := GetProcAddress(hDLL,'mysql_real_connect');
    @mysql_close           := GetProcAddress(hDLL,'mysql_close');
    @mysql_select_db       := GetProcAddress(hDLL,'mysql_select_db');
    @mysql_create_db       := GetProcAddress(hDLL,'mysql_create_db');
    @mysql_drop_db         := GetProcAddress(hDLL,'mysql_drop_db');
    @mysql_query           := GetProcAddress(hDLL,'mysql_query');
    @mysql_real_query      := GetProcAddress(hDLL,'mysql_real_query');
    @mysql_shutdown        := GetProcAddress(hDLL,'mysql_shutdown');
    @mysql_refresh         := GetProcAddress(hDLL,'mysql_refresh');
    @mysql_kill            := GetProcAddress(hDLL,'mysql_kill');
    @mysql_ping            := GetProcAddress(hDLL,'mysql_ping');
    @mysql_stat            := GetProcAddress(hDLL,'mysql_stat');
    @mysql_options         := GetProcAddress(hDLL,'mysql_options');
    @mysql_escape_string   := GetProcAddress(hDLL,'mysql_escape_string');
    @mysql_get_server_info := GetProcAddress(hDLL,'mysql_get_server_info');
    @mysql_get_client_info := GetProcAddress(hDLL,'mysql_get_client_info');
    @mysql_get_host_info   := GetProcAddress(hDLL,'mysql_get_host_info');
    @mysql_get_proto_info  := GetProcAddress(hDLL,'mysql_get_proto_info');
    @mysql_list_fields     := GetProcAddress(hDLL,'mysql_list_fields');
    @mysql_list_processes  := GetProcAddress(hDLL,'mysql_list_processes');
    @mysql_list_dbs        := GetProcAddress(hDLL,'mysql_list_dbs');
    @mysql_list_tables     := GetProcAddress(hDLL,'mysql_list_tables');
    @mysql_data_seek       := GetProcAddress(hDLL,'mysql_data_seek');
    @mysql_row_seek        := GetProcAddress(hDLL,'mysql_row_seek');
    @mysql_field_seek      := GetProcAddress(hDLL,'mysql_field_seek');
    @mysql_fetch_row       := GetProcAddress(hDLL,'mysql_fetch_row');
    @mysql_fetch_lengths   := GetProcAddress(hDLL,'mysql_fetch_lengths');
    @mysql_fetch_field     := GetProcAddress(hDLL,'mysql_fetch_field');
    @mysql_use_result      := GetProcAddress(hDLL,'mysql_use_result');
    @mysql_store_result    := GetProcAddress(hDLL,'mysql_store_result');
    @mysql_free_result     := GetProcAddress(hDLL,'mysql_free_result');
    @mysql_thread_id       := GetProcAddress(hDLL,'mysql_thread_id');
    //EOZEOS//
    //So far ZEOS, but we have some more library functions!
    //Added by [EMAIL PROTECTED]:
    @mysql_insert_id       := GetProcAddress(hDLL, 'mysql_insert_id');
    @mysql_fetch_fields    := GetProcAddress(hDLL, 'mysql_fetch_fields');
    @mysql_num_fields      := GetProcAddress(hDLL, 'mysql_num_fields');
    //EOArTee

    //ZEOS:
    Result := True;
  end else
    raise Exception.Create(Format('Library %s not found',[DLL]));
end;
//So far ZEOS

constructor TMyDB.Create;
begin
  FLibrary:=DEFAULT_DLL_LOCATION;
  DLL:=FLibrary;
  FHost:='localhost';
  FPort:=MY_DEFAULT_PORT;
  FActive:=False;
  ActivateOnLoad:=False;
  FFieldNames:=TStringList.Create;
  FRealConnect:=False;
  FConnectOptions:=_CLIENT_COMPRESS or _CLIENT_CONNECT_WITH_DB;
  inherited;
end;

procedure TMyDB.Loaded;
begin
  inherited;
  if ActivateOnLoad then
    SetActive(True);
end;

procedure TMyDB.Close;
begin
  try
    mysql_close(@MyHandle);
  except
    raise Exception.Create('An error occured while closing');
  end;
  FActive:=False;
  if Assigned(FOnClose) then
    FOnClose(Self);
end;

procedure TMyDB.Connect;
begin
  //Allow user to change shared library
  if FLibrary<>'' then
    DLL:=FLibrary;
  if (hDLL=0) and not MySQLLoadLib then exit;
  //Succesfully loaded
  if FActive then Close;  //Close if already active

  mysql_init(@MyHandle);  //backward compatability??
//  if MyHandle=nil then
//    exit;
  if FRealConnect then
    try
      PMyHandle:= mysql_real_connect(@MyHandle, PChar(String(Host)), 
PChar(String(User)), PChar(String(Pass)),
                 PChar(String(FDataBase)), FPort, nil 
{PChar(String(FUnixSock))}, 0{ FConnectOptions});
      FActive := PMyHandle<>nil;
    except
      FActive:=False;
    end
  else
    begin
      PMyHandle:=mysql_connect(@MyHandle, PChar(Host), PChar(User), 
PChar(Pass));
      FActive := PMyHandle<>nil;
      //Select database if assigned:
      if FActive and (FDataBase<>'') then
        mysql_select_db(@MyHandle, PChar(FDataBase));
    end;

  //Don't know why, but hangs if in componentstate:
  if FActive and not (csDesigning in ComponentState) then
    begin
      //Fill in some variables:
      //If compiled with wrong version, the MYSQL type may be wrong,
      //Therefore an try-except:
      try
      //It's too risky. i go figure out what's happening.
//        FServerVersion:=MyHandle.server_version;
//        FCharSet:=MyHandle.charset;
//        FHostInfo:=MyHandle.host_info;
//        FInfo:=MyHandle.info;
      except
        //Wrong DLL. Adjust compiler switches of unit MyDB.;
      end;
    end;
  if FActive and Assigned(FOnOpen) then
    FOnOpen(Self);
end;

procedure TMyDB.SetActive;
begin
  {
  if (csLoading in ComponentState) and
     not (csDesigning in ComponentState) then
    begin
      ActivateOnLoad:=DBActive;
      exit;
    end;}
  if DBActive and not FActive then
    Connect(FHost, FUser, FPass);
  if FActive and not DBActive then
    Close;
end;

procedure TMyDB.CreateDatabase;
begin
  if FActive then
    mysql_create_db(@MyHandle, PChar(Database));
end;

procedure TMyDB.DropDatabase;
begin
  if FActive then
    mysql_drop_db(@MyHandle, PChar(Database));
  FDatabase:='';
end;

procedure TMyDB.SelectDatabase;
begin
  if FActive then
    mysql_select_db(@MyHandle, PChar(Database));
  FDatabase:=Database;
end;

procedure TMyDB.Kill(Pid:Integer);
begin
  if FActive then
    mysql_kill(@MyHandle, Pid);
end;

function TMyDB.Ping;
begin
  Result:=False;
  if FActive then
    Result:=(mysql_ping(@MyHandle)<>0);
end;

procedure TMyDB.ShutDown;
begin
  if FActive then
    mysql_shutdown(@MyHandle);
end;

procedure TMyDB.StoreResult;
var i,j:Integer;
    row:mysql_row;
    fields:mysql_fields;
    TotMem:Integer;
begin
  FHasResult:=False;
  if Res<>nil then
    begin
      FHasResult:=True;
      //fetch rows
      SetLength (FQueryResult, Integer(res^.row_count));
      SetLength (FExtQueryResult, Integer(res^.row_count));
      TotMem:=0;
      for i:=0 to res^.row_count-1 do
        begin
          row:=mysql_fetch_row(res)^;
          SetLength (FQueryResult[i], res^.field_count);
          SetLength (FExtQueryResult[i], res^.field_count);
          for j:=0 to res^.field_count-1 do
            begin
              if row[j]=nil then
                FExtQueryResult[i,j].IsNull :=True;
              FQueryResult[i,j]:=row[j];
              TotMem:=4+length(FQueryResult[i,j]);
            end;
          //Check ranges; break if rowlimit or memory limit reached:
          if ((FFetchRowLimit<>0) and ((i+1)>=FFetchRowLimit)) or
             ((FFetchMemoryLimit<>0) and (TotMem>=FFetchMemoryLimit)) then
            break;
        end;

      //Convert to trivial types:
      if high(FQueryResult)>=0 then
        FResultAsString:=FQueryResult[0][0];

      //definitely not optimized for speed/memory use (ToDo):
      //ToDo = Only create text/html on property request...
      //However code is here now, it'll take 2 times more memory than necessary:
      FResultAsText:='';
      FResultAsHTML:='<TABLE>';
      for i:=0 to high(FQueryResult) do
        begin
          FResultAsText:=FResultAsText+FQueryResult[i][0];
          FResultAsHTML:=FResultAsHTML+'<TR>'+FQueryResult[i][0];
          for j:=1 to high(FQueryResult[0]) do
            begin
              FResultAsText:=FResultAsText+#9+FQueryResult[i][j];
              FResultAsHTML:=FResultAsHTML+'<TD>'+FQueryResult[i][j]+'</TD>';
            end;
          FResultAsText:=FResultAsText+#13+#10;
          FResultAsHTML:=FResultAsHTML+#13+#10;
        end;
      FResultAsHTML:=FResultAsHTML+'</TABLE>'+#13+#10;

      //Fetch field names
      FFieldNames.Clear;
      SetLength (FFields, mysql_num_fields(res));
      fields:=mysql_fetch_fields(res)^;
      for i:=0 to mysql_num_fields(res)-1 do
        begin
          FFieldNames.Add(fields[i].Name);
          with FFields[i] do begin
            //Copy data mainly for PChar/String converting
            //Makes field info available after resource handle is closed!
            name:=fields[i].name;
            table:=fields[i].table;
            def:=fields[i].def;
            _type:=fields[i]._type;
            length:=fields[i].length;
            max_length:=fields[i].max_length;
            flags:=fields[i].flags;
            decimals:=fields[i].decimals;
          end;
        end;
      //Some more vars:
      FNumFields:=mysql_num_fields(res);
      FRowsAffected:=MyHandle.affected_rows;
      FLastInsertID:=MyHandle.insert_id;
      mysql_free_result(res);
      FHasResult:=True;
      if Assigned (OnSuccess) then
        OnSuccess(Self);
    end
  else //Invalid Result
    begin
      SetLength (FQueryResult, 0);
      FResultAsString:='';
      FResultAsText:='';
      FResultAsHTML:='';
      FNumFields:=0;
      FRowsAffected:=-1;
      FLastInsertID:=-1;
      FFieldNames.Clear;
      FHasResult:=False;
      if Assigned (OnError) then
        OnError (Self);
    end;
end;

procedure TMyDB.Query;
begin
  if not FActive then
    SetActive(True); //Try once if client just performs query

  if FActive then
    begin
      //Allow user to view or edit query:
      FSQL:=SQL;
      if Assigned (OnBeforeQuery) then
        OnBeforeQuery(Self);
      SQL:=FSQL;

      //Perform actual query:
      if 0=mysql_query(@MyHandle, PChar(SQL)) then
        begin
          StoreResult(mysql_store_result(@MyHandle));
        end
      else
        begin
          //StoreResult is able to handle errors and will call OnError as well
          //Calling it with nill forces a result cleanup:
          StoreResult(nil);
        end;
    end;
end;

procedure TMyDB.ListDatabases;
begin
  if FActive then
    StoreResult(mysql_list_dbs(@MyHandle, PChar(wildcard)));
end;

procedure TMyDB.ListTables;
begin
  if FActive then
    StoreResult(mysql_list_tables(@MyHandle, PChar(wildcard)));
end;

procedure TMyDB.ListProcesses;
begin
  if FActive then
    StoreResult(mysql_list_processes(@MyHandle));
end;

procedure TMyDB.ListFields;
begin
  if FActive then
    StoreResult(mysql_list_fields(@MyHandle, PChar(table), PChar(wildcard)));
end;

function TMyDB.GetServerInfo;
begin
  if FActive then
    Result:=mysql_get_server_info(@MyHandle)
  else
    Result:='Inactive';
end;

procedure TMyDB.SetPort;
begin
  if (Port<=0) or (Port>65535) then //Simply don't accept value
    exit;
  if Port<>MY_DEFAULT_PORT then //Force real connect:
    FRealConnect:=True;
  FPort:=Port;
end;

procedure TMyDB.SetRealConnect;
begin
  if not DoRealConnect then //Only connect to default port:
    FPort:=MY_DEFAULT_PORT;
  FRealConnect:=DoRealConnect;
end;

function TMyDB.GetLastError;
//var B:array[01..MYSQL_ERRMSG_SIZE] of Char;
begin

  if FActive then
    begin
      SetLength(Result, 200);
      Result:=myhandle._net.last_error;
    end;
end;


procedure Register;
begin
  RegisterComponents('Kylix_OE', [TMyDB]);
end;


initialization

finalization
  if (hDLL <> 0) and LibLoaded then
    FreeLibrary(hDLL);
end.

Reply via email to