Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Problem mit Umschalten der Verbindung (https://www.delphipraxis.net/188076-problem-mit-umschalten-der-verbindung.html)

Delbor 28. Jan 2016 14:45

Datenbank: MySQL • Version: 5.9xxx • Zugriff über: Firedac

Problem mit Umschalten der Verbindung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi zusammen

Ich schlage mich noch immer damit herum, Servervariablen von MySQL abzufragen.
Offensichtlich handelt es sich dabei nicht um Metainformationen. Diese beschreiben meine eigene Datenbank. Ich brauche aber Variablen, die vom Server bereitgestellt werden, wie zum Beispiel maxallowedpacket, das die Maximalgrösse der Daten angibt, die in einem Feld gespeichert werden können.
Also versuche ich nun, die MySQL-Tabellen mit 'normalem' SQL abzufragen, was teilweise auch gelingt.
Das Problem dabei ist, das MySQL für jede Verbindung eine eigene Instanz einer Variablen bereitstellt. Desshalb benutze ich eine einzige FDConnection-Komponente und verbinde sie dynamisch mit dem Server.
So, wie ich das bislang verstanden habe, kann ich aber nicht mit einem Query (oder was auch immer)auf Datenbank B zugreifen, wenn in der Verbindungsdefinition Datenbank A angegeben ist.

Deshalb sieht meine CM-First.Create-Procedure zur Zeit so aus:
Delphi-Quellcode:
procedure TCM_First.FormCreate(Sender: TObject);
  var i,j: integer; QueryResult :TQueryResultClass;
      SQLString, Category : String;
begin
  FProcedureReport := TStringList.Create;
  ApplicationManager := TWinManager.Create(CM_First);
  FDMySQLDml:= TFDMySQLDml.Create(Self);
  FDMySQLDml.DefinePerformanceschemaConnection;
  FProcedureReport.Add('TFDMySQLDml.Create');
  FProcedureReport.Add('DefinePerformanceschemaConnection-Aufruf');
  FProcedureReport.Add(' ');
  ServerInfoFrame1.CatalogInformation;
  FProcedureReport.Add('ServerInfoFrame1.CatalogInformation-Aufruf');
  FDMySQLDml.OnFoundedCategory := Self.DoOnFoundedCategory ;
  FDMySQLDml.OnStartCategoryQuery := Self.DoOnStartCategoryQuery;
....
  if FDMySQLDml.DefineContentmasterConnection then
  begin
....
  end
  else
  begin
   ShowMessage('Die Verbindung konnte '+ #13#10 + ' nicht hergestellt werden.');
  end;
  FProcedureReport.Add(' ');
  FProcedureReport.Add('FDMySQLDml.FDConnectionMySql.ConnectionName := '+FDMySQLDml.FDConnectionMySql.ConnectionName);
  FProcedureReport.Add('FDMySQLDml.FDConnectionMySql.Params.Database := '+FDMySQLDml.FDConnectionMySql.Params.Database);
  FProcedureReport.Add('FDMySQLDml.FDQueryMain.ConnectionName := '+FDMySQLDml.FDQueryMain.ConnectionName);
  FProcedureReport.Add('FDMySQLDml.FDQueryCategory.ConnectionName := '+FDMySQLDml.FDQueryCategory.ConnectionName);
  FProcedureReport.Add('FDMySQLDml.FDMySQLQueryInfo.ConnectionName := '+FDMySQLDml.FDMySQLQueryInfo.ConnectionName);
end;
Einige für diese Frage nicht relevante Zeilen habe ich durch Punkte ersetzt.
Die DefineContentmasterprocedur und die DefinePerformanceschemaConnection sehen so aus - beide sind anundfürsich gleich; der Unterschied liegt nur in der zugewiesenen Datenbank:
Delphi-Quellcode:
function TFDMySQLDml.DefineContentmasterConnection: Boolean;
  var LIndent : String;
begin
  if (FHost <> 'localhost') or (FDataBase <> 'contentmasterdata') then
    Exit;
  LIndent := '   -  ';
  FDConnectionMySQL.Close;
//  FDQueryMain.Release
  FDConnectionMySQL.Params.Add('DriverID=MySQL');
  FDConnectionMySQL.Params.Add('Server=' + FHost);
  FDConnectionMySQL.Params.Add('Port=' + FPort);
  FDConnectionMySQL.Params.Add('Database=' + FDataBase);
  FDConnectionMySQL.Params.Add('User_Name=root');
  FDConnectionMySQL.Open;
  Result := True;
  CM_First.ProcedureReport.Add(' ');
  CM_First.ProcedureReport.Add('FUNCTION TFDMySQLDml.DefineContentmasterConnection');
  CM_First.ProcedureReport.Add('--------------------------------------------------');
  CM_First.ProcedureReport.Add('TFDMySQLDml.FDConnectionMySQL.Params.DriverID := '+ FDConnectionMySQL.Params.DriverID);
  CM_First.ProcedureReport.Add('TFDMySQLDml.FDConnectionMySQL.Params.Database := '+ FDConnectionMySQL.Params.Database);
end;
Im Anhang ist zu sehe, was mir ProcedurReport schliesslich im Memo ausgibt...

Als ich die FDConnection im Datamodul angelegt hatte, setzte ich deren Property Connection auf eine von mir im Datenexplorer definierte Verbindung.

Was mache ich falsch?

Gruss
Delbor

baumina 28. Jan 2016 14:58

AW: Problem mit umschalten der Verbindund
 
Zitat:

Zitat von Delbor (Beitrag 1328649)
So, wie ich das bislang verstanden habe, kann ich aber nicht mit einem Query (oder was auch immer)auf Datenbank B zugreifen, wenn in der Verbindungsdefinition Datenbank A angegeben ist.

Liegen beide Datenbanken auf dem gleichen Server, dann einfach

SQL-Code:
select * from DBName1.TabName, DBName2.TabName


EDIT: Achso, bevor du FDConnectionMySQL.Params.Add machst, vielleicht sicherheitshalber vorher ein FDConnectionMySQL.Params.Clear machen.

Edit2: Servervariablen kannst du dir datenbankunabhängig folgendermaßen anzeigen lassen

SQL-Code:
show variables like 'max_allowed_packet'

Delbor 28. Jan 2016 16:05

AW: Problem mit umschalten der Verbindund
 
Hi Baumina

Danke für deine Antwort. Aber du hast das etwas falsch verstanden. Die eine - coontentmasterdata - ist meine DB. Die anderen sind Datenbanken von MySQL, die zB. die Servervariablen enthalten.

Alle möglichen Verbindungsarten in FireDac nennen eine bestimmte Datenbank.
Daher glaubte ich, Firedac könne genau zu der Datenbank verbinden, die in der Definition angegeben ist.

Das das auf Seiten des (selben) Servers möglich ist, war mir soweit bekannt - will heissen, mehr im Hinterkopf als wirklich bewusst:
Delphi-Quellcode:
select * from DBName1.TabName, DBName2.TabName
Meine Interpretation bislang war, dass ich unter Firedac für jede Datenbank die Verbindung neu aufbauen muss. Doch da hab ich offensichtlich Verständnisprobleme.

Unter DBExpress war zB. das Möglich, um Max_ALLOWED_PACKET neu zu setzeen:
Delphi-Quellcode:
procedure TFDMySQLDml.SetMaxAllowedPacket(Value : integer);
  var SQLString: AnsiString;
begin
  FDQueryMain.SQL.Text := 'SET @@global.Max_ALLOWED_PACKET = '+ IntToStr(Value);
  FDQueryMain.ExecSQL(True);
  FDQueryMain.Close;
end;
Ich würde mich aber wundern, wenn das unter Firedac funktioniert...
Wobei sich dann auch die Frage stelllt, wie der Server angewiesen wird, den Variablenwert global für diese Verbindung und nicht nur temporär zu ändern.

Gruss
Delbor

Sir Rufo 28. Jan 2016 17:35

AW: Problem mit umschalten der Verbindund
 
Zitat:

Zitat von Delbor (Beitrag 1328658)
Wobei sich dann auch die Frage stelllt, wie der Server angewiesen wird, den Variablenwert global für diese Verbindung und nicht nur temporär zu ändern.

Jede Verbindung zum Server ist eine eigene Session auf dem Server. Zu jeder Session gibt es Session-Variablen, die ich abfragen und auch setzen kann.

Trenne ich die Verbindung, dann wird auch die Session beendet und die gesetzen Werte der Session-Variablen gehen den gleichen Weg wie die Session -> ab ins Nirwana.

Wie setzt man nun Session-Variablen, so dass diese bei einer Verbindung auch so gesetzt sind, wie man das möchte?

:arrow: Man bestückt den
Delphi-Quellcode:
OnAfterConnect
Event der Verbindungs-Komponente und stellt dort alles ein.

Wenn du etwas global einstellen möchtest, dann musst du das auch entsprechend vermerken:
MySQL Documentation

Many system variables are dynamic and can be changed while the server runs by using the SET statement. For a list, see Section 5.1.5.2, “Dynamic System Variables”. To change a system variable with SET, refer to it as var_name, optionally preceded by a modifier:
  • To indicate explicitly that a variable is a global variable, precede its name by GLOBAL or @@global.. The SUPER privilege is required to set global variables.
  • To indicate explicitly that a variable is a session variable, precede its name by SESSION, @@session., or @@. Setting a session variable normally requires no special privilege, although there are exceptions (such as sql_log_bin.) A client can change its own session variables, but not those of any other client.
  • LOCAL and @@local. are synonyms for SESSION and @@session..
  • If no modifier is present, SET changes the session variable.
(Quelle: MySQL 5.7 Reference Manual - 13.7.4 SET Syntax)

Delbor 28. Jan 2016 23:27

AW: Problem mit umschalten der Verbindund
 
Hi Sir Rufo

Auch dir danke ich für deine Antwort.
Zitat:

Jede Verbindung zum Server ist eine eigene Session auf dem Server. Zu jeder Session gibt es Session-Variablen, die ich abfragen und auch setzen kann.
Trenne ich die Verbindung, dann wird auch die Session beendet und die gesetzen Werte der Session-Variablen gehen den gleichen Weg wie die Session -> ab ins Nirwana.
Genau deshalb verwende ich nur eine einzige Connection-Komponente. Die bewusste DB-Anwendung lief unter DelphiXE4 Pro und DBExpress problemlos.
Dann hab ich mir DelphiXE8 zugelegt - offensichtlich genau einen Tag, bevor Delphi Seattle erschien. Das heisst: die Version des MySQL-Servers, der unter DelphiXE8/DBExpress funktioniert hätte, war offenbar auch schon wieder Geschichte. Eine neue Version des MySql-Servers benötigtete ich, weil ich mir einen neuen Rechner (Win10 Pro/64) zugelegt hatte. Und da ich nun mit den DBExpress-Komponenten keine Verbindung zu MySQL mehr erhielt, entschloss ich mich, auf FireDac umzusteigen.
Erstmal habe ich sämtliche Express-Komponenten durch solche aus dem Firedac-Framework ersetzt. Dabei zeigten sich Probleme bei Prozeduren, die auf Serverfunktionen zugreifen.

Zitat:

select * from DBName1.TabName, DBName2.TabName
Bauminas Codeschnipsel ist mir nicht ganz unbekannt - es wäre auszutesten. Nachträglich fallen mir Beispiele von der MySQL-Seite ein, die vor Abfragen anderer Datenbanken erst mit use zu dieser wechseln. Solche Beispiele scheinen zumindest Bauminas Codeschnipsel zu widersprechen - es sei denn, der Server akzeptiert ein zweifaches use:
Delphi-Quellcode:
use DBName1;
use DBNAme2;
Das wäre in dieser Form aber die direkte Kommunikation mit dem Server über die Kommandozeile.

Zitat:

EDIT: Achso, bevor du FDConnectionMySQL.Params.Add machst, vielleicht sicherheitshalber vorher ein FDConnectionMySQL.Params.Clear machen.
Ja, wär' ja klug, wenn sich die Komponente ihre Parameter nicht so einfach überschreiben lässt.

Gruss
Delbor

Delbor 29. Jan 2016 09:55

AW: Problem mit Umschalten der Verbindung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi zusammen
Das Problem scheint ganz woanders zu liegen. ich hab das Params.Clear wie von Baumina vorgeschlagen, mal eingefügt. Das Resultaat war daselbe wie auf dem Eingangs gezeigten Anhang. Also hab ich in der entsprechenden Routine eine Zeile hinzugefügt, um eine zusätzliche Ausgabe auf dem Memo zu errreichen:
Delphi-Quellcode:
  CM_First.ProcedureReport.Add(' ');
  CM_First.ProcedureReport.Add('FUNCTION TFDMySQLDml.DefineContentmasterConnection');
  CM_First.ProcedureReport.Add('--------------------------------------------------');
  CM_First.ProcedureReport.Add('TFDMySQLDml.FDConnectionMySQL.Params.DriverID := '+ FDConnectionMySQL.Params.DriverID);
  CM_First.ProcedureReport.Add('TFDMySQLDml.FDConnectionMySQL.Params.Database := '+ FDConnectionMySQL.Params.Database);
  CM_First.ProcedureReport.Add('-------------------------------------------------------------------------------------'); //<= Neu
Das Ergebnis ist im Anhang ersichtlich.
Ursprünglich vermutete ich, das das Memo standardmässig über eine gewisse Beschränkung auzugebender Zeichen verfügt und habe deshalb Stringzuweisungen an die Liste, die zwischen den beiden Define-Funktionen erfolgen, deaktiviert. Allerdings hat das Memo die letzte Zeile trotzdem weiterhin verschluckt.
Zeilenweises durchsteppen der Routine ergab, das sämtliche Zeilen korrekt abgearbeite werden und auch diee Variablenbelegungen stimmen.
Da FDConnectionMySQL.Params und das Memo im Grunde beides Listen sind, sind deren beider Indexe nullbasiert - daran kanns also nicht liegen.

Gruss
Delbor


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:39 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz