Browse Source

* 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

michael 20 years ago
parent
commit
35a249fc8f
1 changed files with 92 additions and 59 deletions
  1. 92 59
      fcl/db/sqldb/mysql/mysql4conn.pas

+ 92 - 59
fcl/db/sqldb/mysql/mysql4conn.pas

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