* Patch from Joost van der Sluis

- Made it possible to run 'show...' queries for MySQL
  - Use of the dynamically loaded library (mysql4dyn)
  - implemented UpdateIndexDefs
  - Support for more then one query for each connection
This commit is contained in:
michael 2005-01-24 10:53:04 +00:00
parent f04a7f8f86
commit 35a249fc8f

View File

@ -2,10 +2,17 @@ unit mysql4conn;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
{$Define LinkDynamically}
interface interface
uses uses
Classes, SysUtils,sqldb,mysql4,mysql4_com,db; Classes, SysUtils,sqldb,db,
{$IfDef LinkDynamically}
mysql4dyn,mysql4_comdyn;
{$Else}
mysql4,mysql4_com;
{$EndIf}
Type Type
TMySQLTransaction = Class(TSQLHandle) TMySQLTransaction = Class(TSQLHandle)
@ -14,6 +21,7 @@ Type
TMySQLCursor = Class(TSQLHandle) TMySQLCursor = Class(TSQLHandle)
protected protected
FQMySQL : PMySQL;
FRes: PMYSQL_RES; { Record pointer } FRes: PMYSQL_RES; { Record pointer }
FNeedData : Boolean; FNeedData : Boolean;
FStatement : String; FStatement : String;
@ -30,7 +38,9 @@ Type
FMySQL : PMySQL; FMySQL : PMySQL;
function GetClientInfo: string; function GetClientInfo: string;
function GetServerStatus: String; function GetServerStatus: String;
procedure ConnectMySQL(var HMySQL : PMySQL;H,U,P : pchar);
protected protected
function StrToStatementType(s : string) : TStatementType; override;
Procedure ConnectToServer; virtual; Procedure ConnectToServer; virtual;
Procedure SelectDatabase; virtual; Procedure SelectDatabase; virtual;
function MySQLDataType(AType: enum_field_types; ASize: Integer; var NewType: TFieldType; var NewSize: Integer): Boolean; function MySQLDataType(AType: enum_field_types; ASize: Integer; var NewType: TFieldType; var NewSize: Integer): Boolean;
@ -56,6 +66,8 @@ Type
function StartdbTransaction(trans : TSQLHandle) : boolean; override; function StartdbTransaction(trans : TSQLHandle) : boolean; override;
procedure CommitRetaining(trans : TSQLHandle); override; procedure CommitRetaining(trans : TSQLHandle); override;
procedure RollBackRetaining(trans : TSQLHandle); override; procedure RollBackRetaining(trans : TSQLHandle); override;
procedure UpdateIndexDefs(var IndexDefs : TIndexDefs;TableName : string); override;
Public Public
Property ServerInfo : String Read FServerInfo; Property ServerInfo : String Read FServerInfo;
Property HostInfo : String Read FHostInfo; Property HostInfo : String Read FHostInfo;
@ -75,6 +87,8 @@ Type
implementation implementation
uses dbconst;
{ TMySQLConnection } { TMySQLConnection }
Resourcestring Resourcestring
@ -103,10 +117,20 @@ begin
DatabaseError(Msg,Comp); DatabaseError(Msg,Comp);
end; end;
function TMySQLConnection.StrToStatementType(s : string) : TStatementType;
begin
S:=Lowercase(s);
if s = 'show' then exit(stSelect);
result := inherited StrToStatementType(s);
end;
function TMySQLConnection.GetClientInfo: string; function TMySQLConnection.GetClientInfo: string;
begin begin
CheckConnected; CheckConnected;
Result:=strpas(mysql_get_client_info); // Ask MvC
Result:=strpas(pchar(mysql_get_client_info));
end; end;
function TMySQLConnection.GetServerStatus: String; function TMySQLConnection.GetServerStatus: String;
@ -115,7 +139,19 @@ begin
Result := mysql_stat(FMYSQL); Result := mysql_stat(FMYSQL);
end; end;
procedure TMySQLConnection.ConnectMySQL(var HMySQL : PMySQL;H,U,P : pchar);
begin
if (HMySQL=Nil) then
New(HMySQL);
mysql_init(HMySQL);
HMySQL:=mysql_real_connect(HMySQL,PChar(H),PChar(U),Pchar(P),Nil,0,Nil,0);
If (HMySQL=Nil) then
MySQlError(Nil,SErrServerConnectFailed,Self);
end;
procedure TMySQLConnection.ConnectToServer; procedure TMySQLConnection.ConnectToServer;
Var Var
H,U,P : String; H,U,P : String;
@ -123,12 +159,7 @@ begin
H:=HostName; H:=HostName;
U:=UserName; U:=UserName;
P:=Password; P:=Password;
if (FMySQL=Nil) then ConnectMySQL(FMySQL,pchar(H),pchar(U),pchar(P));
New(FMySQL);
mysql_init(FMySQL);
FMySQL:=mysql_real_connect(FMySQL,PChar(H),PChar(U),Pchar(P),Nil,0,Nil,0);
If (FMySQL=Nil) then
MySQlError(Nil,SErrServerConnectFailed,Self);
FServerInfo := strpas(mysql_get_server_info(FMYSQL)); FServerInfo := strpas(mysql_get_server_info(FMYSQL));
FHostInfo := strpas(mysql_get_host_info(FMYSQL)); FHostInfo := strpas(mysql_get_host_info(FMYSQL));
end; end;
@ -141,6 +172,9 @@ end;
procedure TMySQLConnection.DoInternalConnect; procedure TMySQLConnection.DoInternalConnect;
begin begin
{$IfDef LinkDynamically}
InitialiseMysql4;
{$EndIf}
inherited DoInternalConnect; inherited DoInternalConnect;
ConnectToServer; ConnectToServer;
SelectDatabase; SelectDatabase;
@ -151,6 +185,10 @@ begin
inherited DoInternalDisconnect; inherited DoInternalDisconnect;
mysql_close(FMySQL); mysql_close(FMySQL);
FMySQL:=Nil; FMySQL:=Nil;
{$IfDef LinkDynamically}
ReleaseMysql4;
{$EndIf}
end; end;
function TMySQLConnection.GetHandle: pointer; function TMySQLConnection.GetHandle: pointer;
@ -181,6 +219,11 @@ begin
begin begin
C.FRes:=Nil; C.FRes:=Nil;
end; end;
if (c.FQMySQL <> Nil) then
begin
mysql_close(c.FQMySQL);
c.FQMySQL:=Nil;
end;
end; end;
procedure TMySQLConnection.PrepareStatement(cursor: TSQLHandle; procedure TMySQLConnection.PrepareStatement(cursor: TSQLHandle;
@ -191,6 +234,9 @@ begin
FStatement:=Buf; FStatement:=Buf;
if StatementType=stSelect then if StatementType=stSelect then
FNeedData:=True; FNeedData:=True;
ConnectMySQL(FQMySQL,FMySQL^.host,FMySQL^.user,FMySQL^.passwd);
if mysql_select_db(FQMySQL,pchar(DatabaseName))<>0 then
MySQLError(FQMySQL,SErrDatabaseSelectFailed,Self);
end end
end; end;
@ -218,14 +264,14 @@ begin
C:=Cursor as TMysqlCursor; C:=Cursor as TMysqlCursor;
If (C.FRes=Nil) then If (C.FRes=Nil) then
begin begin
if mysql_query(FMySQL,Pchar(C.FStatement))<>0 then if mysql_query(c.FQMySQL,Pchar(C.FStatement))<>0 then
MySQLError(FMYSQL,Format(SErrExecuting,[StrPas(mysql_error(FMySQL))]),Self) MySQLError(c.FQMYSQL,Format(SErrExecuting,[StrPas(mysql_error(c.FQMySQL))]),Self)
else else
begin begin
C.RowsAffected := mysql_affected_rows(FMYSQL); C.RowsAffected := mysql_affected_rows(c.FQMYSQL);
C.LastInsertID := mysql_insert_id(FMYSQL); C.LastInsertID := mysql_insert_id(c.FQMYSQL);
if C.FNeedData then if C.FNeedData then
C.FRes:=mysql_use_result(FMySQL); C.FRes:=mysql_use_result(c.FQMySQL);
end; end;
end; end;
end; end;
@ -280,7 +326,6 @@ var
field: PMYSQL_FIELD; field: PMYSQL_FIELD;
DFT: TFieldType; DFT: TFieldType;
DFS: Integer; DFS: Integer;
WasClosed: Boolean;
begin begin
// Writeln('MySQL: Adding fielddefs'); // Writeln('MySQL: Adding fielddefs');
@ -288,7 +333,7 @@ begin
If (C.FRes=Nil) then If (C.FRes=Nil) then
begin begin
// Writeln('res is nil'); // Writeln('res is nil');
MySQLError(FMySQL,SErrNoQueryResult,Self); MySQLError(c.FQMySQL,SErrNoQueryResult,Self);
end; end;
// Writeln('MySQL: have result'); // Writeln('MySQL: have result');
FC:=mysql_num_fields(C.FRes); FC:=mysql_num_fields(C.FRes);
@ -329,7 +374,7 @@ begin
if C.Row=nil then if C.Row=nil then
begin begin
// Writeln('LoadFieldsFromBuffer: row=nil'); // Writeln('LoadFieldsFromBuffer: row=nil');
MySQLError(FMySQL,SErrFetchingData,Self); MySQLError(c.FQMySQL,SErrFetchingData,Self);
end; end;
Row:=C.Row; Row:=C.Row;
FC := mysql_num_fields(C.FRES); FC := mysql_num_fields(C.FRES);
@ -520,55 +565,43 @@ begin
end; end;
end; end;
Function GetSQLStatementType(SQL : String) : TStatementType; procedure TMySQLConnection.UpdateIndexDefs(var IndexDefs : TIndexDefs;TableName : string);
Var var qry : TSQLQuery;
L : Integer;
cmt : boolean;
P,PE,PP : PChar;
S : string;
T : TStatementType;
begin begin
Result:=stNone; if not assigned(Transaction) then
L:=Length(SQL); DatabaseError(SErrConnTransactionnSet);
If (L=0) then
Exit; qry := tsqlquery.Create(nil);
P:=Pchar(SQL); qry.transaction := Transaction;
PP:=P; qry.database := Self;
Cmt:=False; with qry do
While ((P-PP)<L) do
begin begin
if not (P^ in [' ',#13,#10,#9]) then ReadOnly := True;
begin sql.clear;
if not Cmt then sql.add('show index from ' + TableName);
begin open;
// Check for comment.
Cmt:=(P^='/') and (((P-PP)<=L) and (P[1]='*'));
if not (cmt) then
Break;
end
else
begin
// Check for end of comment.
Cmt:=Not( (P^='*') and (((P-PP)<=L) and (P[1]='/')) );
If not cmt then
Inc(p);
end;
end;
inc(P);
end; end;
PE:=P+1;
While ((PE-PP)<L) and (PE^ in ['0'..'9','a'..'z','A'..'Z','_']) do while not qry.eof do with IndexDefs.AddIndexDef do
Inc(PE); begin
Setlength(S,PE-P); Name := trim(qry.fieldbyname('Key_name').asstring);
Move(P^,S[1],(PE-P)); Fields := trim(qry.fieldbyname('Column_name').asstring);
S:=Lowercase(s); If Name = 'PRIMARY' then options := options + [ixPrimary];
For t:=stselect to strollback do If qry.fieldbyname('Non_unique').asinteger = 0 then options := options + [ixUnique];
if (S=StatementTokens[t]) then qry.next;
Exit(t); { while (name = qry.fields[0].asstring) and (not qry.eof) do
begin
Fields := Fields + ';' + trim(qry.Fields[2].asstring);
qry.next;
end;}
end;
qry.close;
qry.free;
end; end;
function TMySQLConnection.GetTransactionHandle(trans: TSQLHandle): pointer; function TMySQLConnection.GetTransactionHandle(trans: TSQLHandle): pointer;
begin begin
Result:=Nil; Result:=Nil;