还有一个法子,直接进行使用libmysql.dll的倒出。
什么都不用通过,直接tcp/ip 连接过去。速度极快。
倒出代码如下。封装了一个单元。
unit _libmysq;
{This is a more complete unit to interface with MySQL Server from Delphi
This work was started by Blestan Tabakov. I have included the rest of the
functionality in libmysql.dll.
Delphi 3 Interface to LibMYSQL.dll (Current libmysql.dll version is 3.22)
June 1998
Bob Silva bsilva@umesd.k12.or.us
To find out more on this get the C API docs from www.tcx.se (makers of MySQL)}
{TODO: Implement as a VCL I dont think I have the knowledge to make it use Delphis
data controls but Ill look into it, I dont think the component will be too hard to
implement in the near future}
interface
uses Dialogs,Sysutils;
const
{General Declarations}
MYSQL_ERRMSG_SIZE=200;
MYSQL_PORT=5555;
LOCAL_HOST='localhost';
MYSQL_UNIX_ADDR='/tmp/mysql.sock';
NAME_LEN=64;
PROTOCOL_VERSION=10;
MYSQL_SERVER_VERSION='3.21.18-beta';
FRM_VER=6;
MYSQL_VERSION_ID=32115;
{Refresh Options}
REFRESH_GRANT=1;
REFRESH_LOG=2;
REFRESH_TABLES=4;
REFRESH_HOSTS=8;
REFRESH_FAST=32768;
{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;
type
ENUM_FIELD_TYPES= byte;
MY_BOOL= shortint;
GPTR= pchar;
SOCKET= word;
PCardinal= ^Cardinal; //Delphi didnt like my ^Cardinal as a return value from a function
{Enumerate return-status codes and option codes}
mysql_status=(MYSQL_STATUS_READY, MYSQL_STATUS_GET_RESULT, MYSQL_STATUS_USE_RESULT);
mysql_option=(MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS);
PUSED_MEM=^USED_MEM;
USED_MEM=record
next
used_mem;
left,size: Cardinal;
end;
ERR_PROC=procedure;
PMEM_ROOT=^MEM_ROOT;
MEM_ROOT=record
free,used
used_mem;
min_malloc,block_size: Cardinal;
error_handler:err_proc;
end;
NET=record
fd: socket;
fcntl: integer;
buff,buff_end,write_pos: pchar;
last_error: array[01..MYSQL_ERRMSG_SIZE] of char;
last_errno,max_packet,timeout,pkt_nr: Cardinal;
error,return_errno, compress: MY_BOOL;
end;
PMYSQL_FIELD=^MYSQL_FIELD;
MYSQL_FIELD=record
name,table,def: pchar;
_type: ENUM_FIELD_TYPES;
length,max_length,flags,decimals: Cardinal;
end;
MYSQL_FIELD_OFFSET= Cardinal;
(*************HELP HERE IF YOU CAN*************)
{The C def for this is: typedef byte **MYSQL_ROW;
Blestan originally used the array struct below, but I could not get it to
work like that.
Blestan Code: mysql_row=array[00..$ffff div sizeof(pchar)] of pchar;
My def of a smaller array seems to solve the problem, but if you were to return
a very large result set, Im sure it will AV. So if you can translate the C Code:
Earlier in code: typedef char byte;
typedef byte **MYSQL_ROW; into an adequate Delphi type then please do and let
me know how you did it. I could get it to return rows using mysql_row: ^PChar; but
I couldnt figure out how to index into it like that.}
PMYSQL_ROW=^MYSQL_ROW;
MYSQL_ROW= array[00..$ff] of pchar;
//MYSQL_ROW= ^PChar;
(*********************************************)
PMYSQL_ROWS=^MYSQL_ROWS;
MYSQL_ROWS=record
next: PMYSQL_ROWS;
data: PMYSQL_ROW;
end;
MYSQL_ROW_OFFSET= PMYSQL_ROWS;
PMYSQL_DATA= ^MYSQL_DATA;
MYSQL_DATA= record
rows, fields: Cardinal;
data: PMYSQL_ROWS;
alloc: MEM_ROOT;
end;
PMYSQL_OPTIONS=^_MYSQL_OPTIONS;
_MYSQL_OPTIONS= record
connect_timeout: Cardinal;
compress: MY_BOOL;
end;
PMYSQL=^MYSQL;
MYSQL= record
_net: NET;
host,user,passwd,unix_socket,server_version,host_info,info,db: pchar;
port,client_flag,server_capabilities,protocol_version,field_count: Cardinal;
thread_id, affected_rows, insert_id, extra_info:longint;
status: mysql_status;
fields: PMYSQL_FIELD;
field_alloc: MEM_ROOT;
free_me, reconnect: MY_BOOL;
end;
PMYSQL_RES=^MYSQL_RES;
MYSQL_RES= record
row_count: longint;
field_count, current_field: Cardinal;
fields: PMYSQL_FIELD;
data: PMYSQL_DATA;
data_cursor: PMYSQL_ROWS;
field_alloc: MEM_ROOT;
row: PMYSQL_ROW;
current_row: PMYSQL_ROW;
lengths: ^Cardinal;
handle: ^MYSQL;
eof: MY_BOOL;
end;
MYServer= record
Host:String;
User:String;
Passwd:String;
Connected:Byte;
end;
const thelib='libmysql.dll';
(*********ALL functions are working unless stated otherwise*************)
{If you can figure why why one of the ones marked bad is not working, please
send me the code to implement it properly}
function mysql_init ( _mysql: pmysql)
mysql;stdcall; //Added July 23
function mysql_connect( _mysql: pmysql; const host,user,passwd
char)
mysql;stdcall;
{Non-functional: dont know why yet: I think you can do without it for now}
{UPDATE: Folkert Klemme reports that this call has worked in his environment}
function mysql_real_connect(_mysql: pmysql; const host, user, passwd, db
char;
port:Cardinal; unix_socket
Char;clientflag:Cardinal)
mysql;stdcall;
procedure mysql_close( _mysql: pmysql); stdcall;
function mysql_select_db(_mysql
mysql;const DB: pchar):integer; stdcall;
function mysql_query(_mysql
mysql;const query: pchar):integer;stdcall;
{Real Query not implemented in current version of libmysql.dll (timestamp:353be33a)}
{UPDATE: Real_Query still not implemented in 3.22 version of libmysql.dll}
// function mysql_real_query(_mysql
mysql;const query: pchar;length: Cardinal):integer;stdcall;
function mysql_create_db(_mysql
mysql; const DB
Char):integer;stdcall;
function mysql_drop_db(_mysql
mysql; const DB
Char):integer; stdcall;
function mysql_shutdown(_mysql: pmysql): Integer; stdcall;
{Although undocumented, I believe this is to reload the permissions table;
documentation calls for a reload function which there is none in libmysql.dll,
so I think this may be a replacement, it takes a Cardinal for options but I cant find out
what those options are since its not documented}
{UPDATE: David Blackburn pointed out to me that the 'refresh_options' were defined
in one of the header files that came with the 3.22 WinClients released by TCX, Constants
have been added to use this call properly}
function mysql_refresh(_mysql
mysql; refresh_options: Cardinal):integer; stdcall;
function mysql_kill(_mysql
mysql; pid:longint):integer; stdcall;
function mysql_ping(_mysql
mysql):integer; stdcall; //Added July 23
function mysql_stat(_mysql
mysql)
char; stdcall;
function mysql_get_server_info(_mysql
mysql)
Char; stdcall;
function mysql_get_client_info
Char; stdcall;
function mysql_get_host_info(_mysql
mysql)
Char;stdcall;
function mysql_get_proto_info(_mysql
mysql):Cardinal;stdcall;
function mysql_list_dbs(_mysql
mysql;wild: pchar)
mysql_res; stdcall;
function mysql_list_tables(_mysql: pmysql; const wild: pchar)
mysql_res; stdcall;
function mysql_list_fields(_mysql: pmysql;const table,wild: pchar)
mysql_res; stdcall;
function mysql_list_processes(_mysql: pmysql)
mysql_res; stdcall;
function mysql_store_result(_mysql
mysql)
mysql_res; stdcall;
function mysql_use_result(_mysql
mysql)
mysql_res; stdcall;
function mysql_options(_mysql
mysql; _option:mysql_option; const arg
Char):Integer;stdcall;
procedure mysql_free_result(result
mysql_res); stdcall;
procedure mysql_data_seek(result
mysql_res; offset:Cardinal); stdcall;
{Row seek is probably functional if I knew how to test it;
I think its a matter of saving a particular row pointer in a mysql_row_offset struct;
then later make a call to row_seek to restore the data_cursor to that row;
then a fetch_row will return the next row after that???? I have no need for it so you tell me}
function mysql_row_seek(result
mysql_res; row:mysql_row_offset):mysql_row_offset;stdcall;
{Field Seek is not implemented in current version of libmysql.dll(timestamp:353be33a)}
{UPDATE: Field_Seek has been implemented in 3.22 version of libmysql.dll that was released
by TCX in MySQL 3.22.4 Clients for Win32}
function mysql_field_seek(result
mysql_res;offset:mysql_field_offset):mysql_field_offset;stdcall
function mysql_fetch_row(result
mysql_res)
mysql_row;stdcall;
{I dont think fetch_length is working properly because of the way that I set up the MYSQL_ROW array}
{UPDATE: The function is supposed to return a POINTER to a Cardinal, I missed that
in my first implementation, sorry, still havent tested it though}
function mysql_fetch_lengths(result
mysql_res)
Cardinal;stdcall;
function mysql_fetch_field(handle: pmysql_res)
mysql_field; stdcall;
{--- writer by conquer (conquer@xinhuabookstore.com) 2001.4.22 ----}
function Connect_Mysql_Server(var db:MYSQL;Server:MYServer;Port:integer):Boolean;
function Select_Mysql_DB(var db:MYSQL;DBName:String):Boolean;
function Query_Mysql(var db:MYSQL; query:String):Boolean;
function Store_Mysql_Result(var db:MYSQL)
MYSQL_RES;
procedure Free_Mysql_Result(var myresult
mysql_res);
function Fetch_Mysql_Row(var myresult
mysql_res)
mysql_row;
procedure Close_Mysql_Server(var db:MYSQL;Server:MYServer);
implementation
function mysql_init ( _mysql: pmysql)
mysql;stdcall;external thelib; //Added July 23
function mysql_connect( _mysql: pmysql; const host,user,passwd
char)
mysql;stdcall;external thelib;
function mysql_real_connect(_mysql: pmysql; const host, user, passwd, db
char;
port:Cardinal; unix_socket
Char;clientflag:Cardinal)
mysql;stdcall;external thelib;
procedure mysql_close( _mysql: pmysql); stdcall;external thelib;
function mysql_select_db(_mysql
mysql;const DB: pchar):integer; stdcall;external thelib;
function mysql_query(_mysql
mysql;const query: pchar):integer;stdcall;external thelib;
// function mysql_real_query(_mysql
mysql;const query: pchar;length: Cardinal):integer;stdcall;external thelib;
function mysql_create_db(_mysql
mysql; const DB
Char):integer;stdcall;external thelib;
function mysql_drop_db(_mysql
mysql; const DB
Char):integer;stdcall;external thelib;
function mysql_shutdown(_mysql: pmysql): Integer; stdcall;external thelib;
function mysql_refresh(_mysql
mysql; refresh_options: Cardinal):integer;stdcall;external thelib;
function mysql_kill(_mysql
mysql; pid:longint):integer;stdcall;external thelib;
function mysql_ping(_mysql
mysql):integer; stdcall;external thelib; //Added July 23
function mysql_stat(_mysql
mysql)
char; stdcall;external thelib;
function mysql_get_server_info(_mysql
mysql)
Char;stdcall;external thelib;
function mysql_get_client_info
Char;stdcall;external thelib;
function mysql_get_host_info(_mysql
mysql)
Char;stdcall;external thelib;
function mysql_get_proto_info(_mysql
mysql):Cardinal;stdcall;external thelib;
function mysql_list_dbs(_mysql
mysql;wild: pchar)
mysql_res; stdcall;external thelib;
function mysql_list_tables(_mysql: pmysql; const wild: pchar)
mysql_res; stdcall;external thelib;
function mysql_list_fields(_mysql: pmysql;const table,wild: pchar)
mysql_res; stdcall;external thelib;
function mysql_list_processes(_mysql: pmysql)
mysql_res; stdcall;external thelib;
function mysql_store_result(_mysql
mysql)
mysql_res; stdcall;external thelib;
function mysql_use_result(_mysql
mysql)
mysql_res;stdcall;external thelib;
function mysql_options(_mysql
mysql; _option:mysql_option; const arg
Char):Integer;stdcall;external thelib;
procedure mysql_free_result(result
mysql_res); stdcall;external thelib;
procedure mysql_data_seek(result
mysql_res; offset:Cardinal); stdcall;external thelib;
function mysql_row_seek(result
mysql_res; row:mysql_row_offset):mysql_row_offset;stdcall;external thelib;
function mysql_field_seek(result
mysql_res;offset:mysql_field_offset):mysql_field_offset;stdcall;external thelib;
function mysql_fetch_row(result
mysql_res)
mysql_row;stdcall;external thelib;
function mysql_fetch_lengths(result
mysql_res)
Cardinal;stdcall;external thelib;
function mysql_fetch_field(handle: pmysql_res)
mysql_field; stdcall;external thelib;
{--- writer by conquer (conquer@xinhuabookstore.com) 2001.4.22 ----}
{*******************************************************
desc:Connect_flag use to track connection
*******************************************************}
function Connect_Mysql_Server(var db:MYSQL;Server:MYServer;Port:integer):Boolean;
begin
{Connect to server}
try
begin
mysql_init(@db);
db.port:=Port;
//mysql_connect(@db,PChar(Server.Host), PChar(Server.User), PChar(Server.Passwd));
mysql_real_connect(@db, PChar(Server.Host), PChar(Server.User),PChar(Server.Passwd),PChar('xos'),db.port,db.unix_socket,db.client_flag);
if db._net.last_errno = 0 then
begin
result:=true;
Server.Connected:=1; //keep track of connection
end else
begin
result:=false;
Server.Connected:=0;
end;
end;
except
//showmessage(trim(db._net.last_error));
Server.Connected:=0;
result:=false;
exit;
end;
end;
{******************************************************
desc:select db
*******************************************************}
function Select_Mysql_DB(var db:MYSQL;DBName:String):Boolean;
var
err:Integer;
begin
try
begin
err:=mysql_select_db(@db,PChar(DBName));
if (err<>0) then
result:=false
else
result:=true;
end;
except
result:=false;
end;
end;
{*******************************************************
desc:
*******************************************************}
function Query_Mysql(var db:MYSQL; query:String):Boolean;
begin
if (mysql_query(@db,PChar(query))<>0) then
result:=false
else
result:=true;
end;
{*******************************************************
desc: get result dataset
*******************************************************}
function Store_Mysql_Result(var db:MYSQL)
MYSQL_RES;
begin
try
result:=mysql_store_result(@db);
except
result:=nil;
end;
end;
{*******************************************************
desc:
*******************************************************}
procedure Free_Mysql_Result(var myresult
mysql_res);
begin
mysql_free_result( myresult);
end;
{*******************************************************
desc:
*******************************************************}
function Fetch_Mysql_Row(var myresult
mysql_res)
mysql_row;
begin
try
result:=mysql_fetch_row(myresult);
except
result:=nil;
end;
end;
{*******************************************************
desc:
*******************************************************}
procedure Close_Mysql_Server(var db:MYSQL;Server:MYServer);
begin
if (Server.Connected=1) then
mysql_close(@db);
end;
end.