Setting "Server" programmatically with a TFDConnection - mysql

TFDConnection.Params.Server is not a valid published property in Delphi XE7. How can I set the server location programmatically? I have 2 MySQL servers (test and production) that are at different ip's and based on what I am doing in the application, I want to easily switch back and forth between the 2 servers.

Please read the documentation, it tells you exactly how to define a FireDAC connection for MySQL:
Working with Connections (FireDAC)
Connect to MySQL Server (FireDAC)
You would specify the DB server as part of a Connection Definition:
Defining Connection (FireDAC)
Connection Definitions can be defined in an external .ini file, which you can then reference in the TFDManager.ConnectionDefFileName property, or load dynamically using the TFDManager.LoadConnectionDefFile() method.
[MySQL_Connection_1]
DriverID=MySQL
Server=192.168.1.100
...
[MySQL_Connection_2]
DriverID=MySQL
Server=192.168.1.101
...
Or dynamically using the TFDManager.ConnectionDefs property:
var
oDef: IFDStanConnectionDef;
begin
oDef := FDManager.ConnectionDefs.AddConnectionDef;
oDef.Name := 'MySQL_Connection_1';
oDef.DriverID := 'MySQL';
oDef.Server := '192.168.1.100';
...
oDef.Apply;
oDef := FDManager.ConnectionDefs.AddConnectionDef;
oDef.Name := 'MySQL_Connection_2';
oDef.DriverID := 'MySQL';
oDef.Server := '192.168.1.101';
...
oDef.Apply;
var
oParams: TStrings;
begin
oParams := TStringList.Create;
oParams.Add('Server=192.168.1.100');
...
FDManager.AddConnectionDef('MySQL_Connection_1', 'MySQL', oParams);
oParams.Clear;
oParams.Add('Server=192.168.1.101');
...
FDManager.AddConnectionDef('MySQL_Connection_2', 'MySQL', oParams);
Either way, you can then tell TFDConnection which Connection Definition to use to reach each database when needed:
FDConnection1.ConnectionDefName := 'MySQL_Connection_1';
// or: FDConnection1.ConnectionDefName := 'MySQL_Connection_2';
FDConnection1.Connected := True;
Alternatively, you can specify the connection parameters directly in the TFDConnection.Params property if you do not want to pre-define separate connection definitions:
FDConnection1.DriverName := 'MySQL';
FDConnection1.Params.Clear;
FDConnection1.Params.Add('Server=192.168.1.100');
// or: FDConnection1.Params.Values['Server'] := '192.168.1.100';
...
FDConnection1.Connected := True;

Late answer but it's simple to do.
Restating what TLama said in a comment:
The param properties can vary depending on the driver type, so set the driver type to MySQL and then cast the PARAMS as the driver type.
Just do:
(Conn1.Params as TFDPhysMySQLConnectionDefParams).Server := '127.0.0.1';
This way the compiler can verify the param at compile time.

This works for me. Add any additional parameters as needed
var
oParams: TStrings;
begin
oParams := TStringList.Create;
oParams.Add('Server=' + YourServer);
oParams.Add('Database=' + YourDatabase);
oParams.Add('OSAuthent=Yes');
FDManager.AddConnectionDef('CNX1', 'MSSQL', oParams);
FDConnection.ConnectionDefName := 'CNX1';
FDConnection.Connected := true;
if FDConnection.Connected then
ShowMessage('Connected');
oParams.Free;

Related

dbExpress how to show result from query?

var
Connection: TSQLConnection;
SqlSet:TSQLDataSet;
begin
Connection := TSQLConnection.Create(nil);
SqlSet := TSQLDataSet.Create(nil);
SqlSet.SQLConnection:=Connection;
Connection.DriverName := 'MySQL';
Connection.GetDriverFunc := 'getSQLDriverMYSQL';
Connection.LibraryName := 'dbxmys.dll';
Connection.VendorLib := 'libmysql.dll';
Connection.LoginPrompt:=False;
Connection.Params.Values['Database']:=('shadowxx1');
Connection.Params.Values['User_Name']:=('shadowxx1');
Connection.Params.Values['Password']:=('shadowxx1');
Connection.Params.Values['HostName']:=('shadowxx1');
Connection.Open;
Connection.Connected:=True;
SqlSet.CommandType:=ctQuery;
SqlSet.CommandText:= 'SELECT VERSION()';
SqlSet.ExecSQL;
Connection.Close;
Connection.Free;
SqlSet.Free;
end;
Code working , but , how to show result of query or extract it to the grid???
I simply dont find this information, in ADO it was smth like this
DataSrc := TDataSource.Create(Self);
DataSrc.DataSet := ADOQuery;
DataSrc.Enabled := true;
DBGrid1.DataSource := DataSrc;
If someone can - give some examples
And like this dont work
You're using the wrong method. In any of the TDataSet descendants that have it, ExecSQL is for executing queries that return no result set, such as INSERT, UPDATE, DELETE, or CREATE TABLE. See, for instance, TSQLQuery.ExecSQL (emphasis mine)
Executes a query that does not return a set of records.
Call ExecSQL to execute an SQL command that does not return a set of records. This command is a query other than a SELECT query, such as an INSERT, UPDATE, DELETE, or CREATE TABLE query.
Use TSQLQuery.Open to return rows from a SELECT. Something like this should work (untested - I don't use MySQL or DBExpress):
var
Qry: TSQLQuery;
VersionString: String;
// Set up your connection as above, and open it
Qry := TSQLQuery.Create(nil);
Qry.SQLConnection := Connection;
Qry.SQL.Text := 'SELECT VERSION() as DBVersion';
Qry.Open;
if not Qry.IsEmpty then
VersionString := Qry.FieldByName('DBVersion').AsString
else
VersionString := 'No results found';
Qry.Close;
For more information (including step-by-step tutorials), see Using DBExpress Components at the Delphi docwiki. (The one I've linked is for the current Delphi version, but the basic steps for DBExpress are the same since it was introduced.)
If you want a basic video tutorial for using DBExpress in Delphi, you can try DBExpress Data Access Components in Delphi - Delphi 101. I haven't watched it, but it was posted by Embarcadero, the makers of Delphi.

Delphi: Return database names from MySQL using Metadata

I want to know if there is a way to return database names from MySQL using Delphi object TSQLConnection, I know that there is some methods that return table names or field names:
TSQLConnection.getTableNames, TSQLConnection.GetFieldNames
but I can't find a way to get the databases on a specific server.
There s a method called OpenSchema in the TADOconnection object: TADOconnection.Openschema, that can return database names but in the TSQLConnection the method -protected not public- can't return database names.
P.S. I don't want to execute a query like 'show databases' or 'select * from information_schema.schemata'.
any body can help, thanks.
I tried this code and it worked, not sure if it will work for all MySQL, MariaDB versions and all Delphi versions but for me it workes, I am using delphi 6 and MySQL 4.0.25:
function GetMySQLDatabaseNames(AUserName, APassword, AHostName, APort: string; var
AErrorMessage: String): TStrings;
var SQLConnection: TSQLConnection;
ObjectCursor: ISQLCursor;
Status: SQLResult;
Counter: Integer;
Precision: Smallint;
Value: Pointer;
IsBlank: LongBool;
begin
Result:= TStringList.Create;
SQLConnection:= TSQLConnection.Create(nil);
with SQLConnection do
begin
ConnectionName:='dbnames';
DriverName := 'mysql';
Params.Clear;
Params.Values['User_Name'] := AUserName;
Params.Values['Password'] := APassword;
Params.Values['HostName'] := AHostName;
Params.Values['Database'] := 'mysql';
Params.Values['Port'] := APort;
LibraryName :='dbexpmda.dll';
VendorLib := 'not used';
GetDriverFunc :='getSQLDriverMySQLDirect';
LoginPrompt :=False;
try
Connected := True;
Status:= MetaData.getObjectList(eObjTypeDatabase, ObjectCursor);
while Status = SQL_SUCCESS do
begin
Status:= ObjectCursor.getColumnPrecision(4, Precision);
if Status = SQL_SUCCESS then
begin
Value:= AllocMem(Precision);
Status:= ObjectCursor.getString(4, Value, IsBlank);
if Status = SQL_SUCCESS then
if not IsBlank then
Result.Add(PChar(Value));
end;
Status:= ObjectCursor.Next;
end;
Connected := False;
Free;
except
on E: Exception do
begin
AErrorMessage:= AErrorMessage + E.Message+ sLineBreak;
end;
end;
end;
end;
With a query component you can get a list of databases with the following query:
SHOW DATABASES;
I have been looking for this answer for a longer time. Hopefully it will help others.

Lazarus Pascal - DB Connection - clarification

The following code is from the docs here:
Program ConnectDB
var AConnection : TSQLConnection;
Procedure CreateConnection;
begin
AConnection := TIBConnection.Create(nil);
AConnection.Hostname := 'localhost';
AConnection.DatabaseName := '/opt/firebird/examples/employee.fdb';
AConnection.UserName := 'sysdba';
AConnection.Password := 'masterkey';
end;
begin
CreateConnection;
AConnection.Open;
if Aconnection.Connected then
writeln('Succesful connect!')
else
writeln('This is not possible, because if the connection failed, ' +
'an exception should be raised, so this code would not ' +
'be executed');
AConnection.Close;
AConnection.Free;
end.
The main body of the code makes sense to me BUT I don't get where TSQLConnection came from. I cannot use CTRL + Space to autocomplete it either, which means my program has no reference to it. I'm trying to connect to Postgres by the way.
Can someone please state what TSQLConnection is? Thanks!
the TSQLConnection object is defined in the sqldb unit and is the base class for the specific connection components like the TIBConnection (interbase, firebird), TConnectionName (mysql) and TPQConnection (postgres).

Unable to connect to mySql database useing just code

I searched here but did not see an answer .
I am using Delphi2010.
I using Devart Mydac to connect to mySql data base .
When i set the Server, Database, Name , Pass in the component it connects no problem.
BUt when I try to connect just with code it give an error.
begin
MyConnection1.Server:='MyServer';
MyConnection1.Database:='MyDatabase';
MyConnection1.Username:='MyUserName';
MyConnection1.Password:='MyPassword';
MyConnection1.Connected:= True;
MyQuery1.Active:= True;
end;
exception class EMySalExcption with message"#28000 Access denied for
user'username#00.00.00.00'(useing passworkd: YES)'.
Why will the code method cause an error ?
Thanks for your help and patience.
I would comment, but I don't think I have the ability to yet. But I concur with Marco, I am not experienced with this language or product, but I wonder, is the database on a remote machine? First try setting the server to the IP and seeing if that works.
I found this configuration online and removed a few things to get to the core
begin
MyConnection1.LoginPrompt := false;
MyConnection1.Username := 'test';
MyConnection1.Password := 'test';
MyConnection1.Database := 'test';
MyConnection1.Server := '127.0.0.1';
MyConnection1.Port := 3306;
MyConnection1.Connect;
end;
One thing I noticed is it has a disable for the LoginPrompt, where as you don't, also it has a port. I would try setting the ip and port number, if that works, then try setting just the port number. If none of that works try the full implementation here and then go backwards in taking things out and setting server back to hostname
begin
MyConnection1.Pooling := true;
MyConnection1.PoolingOptions.MinPoolSize := 1;
MyConnection1.LoginPrompt := false;
MyConnection1.Options.Charset := 'utf8';
MyConnection1.Options.Direct := true;
MyConnection1.Options.UseUnicode := true;
MyConnection1.Username := 'test';
MyConnection1.Password := 'test';
MyConnection1.Database := 'test';
MyConnection1.Server := '127.0.0.1';
MyConnection1.Port := 3306;
MyConnection1.Connect;
end;
referenced from http://forums.devart.com/viewtopic.php?t=12035

Using parameters with ADO Query (mysql/MyConnector)

Today I downloaded and installed MyConnector so I can use Mysql with ADO, everything installed, OK!, I can make connection with ODBC and do a connection from my delphi environment.
when I build my Query at runetime, I get an error saying :
Project Project1.exe raised exception class EOleException with message 'Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another'. Process stopped. Use Step or Run to continue.
function TForm1.CreateSQL : TADOQuery;
begin
result := TADOQuery.create(self);
with Result do
begin
Connection := MainConnection;
CursorLocation := clUseServer;
CursorType := ctStatic;
CacheSize := 50;
AutoCalcFields := true;
ParamCheck := true;
Prepared := true;
end;
end;
procedure TForm1.login();
begin
with CreateSQL do
try
with SQL do
begin
add('SELECT ');
add(' * ');
add('FROM ');
add(' LisenswebUsers ');
add('WHERE ');
add(' UserName = :MyUsername '); // debugger exception here
add('AND ');
add(' UserPassword = :MyPassword '); // debugger exception here
with Parameters do
begin
ParamByName('MyUsername').value := txtLogin.text;
ParamByName('MyPassword').value := strmd5(txtPassword.text);
end;
Open;
if Recordcount <> 1 then
begin
lblLoggedinAs.Text := format('Du er logget inn som: %s (%s)',[FieldByName('Username').AsString,FieldByName('UserEmailaddress').AsString]);
MainPageControl.ActivePageIndex := 1;
end else
begin
txtPassword.Text := '';
txtPassword.SetFocus;
end;
end;
finally
free;
end;
end;
The strangest thing is that this works if I turn off debugging in delphi.
I would try adding SQL.BeginUpdate/SQL.EndUpdate around the Adds, otherwise the SQL text will be parsed every time you call "Add".
This is generally a good idea, as ADOQuery.SQL is a TStringList that has an OnChange event that sets the CommandText. SetCommandText text then end up calling TADOCommand.AssignCommandText which does a fair amount of work parsing params, and setting CommandObject.CommandText. Sometimes drivers will fail with partial SQL statements, but this stuff looks OK.
I had a similar problem many years ago - that's why I learnt about this stuff!
procedure TForm1.login();
var
Qry : TADOQuery;
begin
Qry := CreateSQL;
try
Qry.SQL.BeginUpdate;
Qry.SQL.Add('SELECT');
Qry.SQL.Add(' *');
Qry.SQL.Add('FROM');
Qry.SQL.Add(' LisenswebUsers');
Qry.SQL.Add('WHERE UserName = :MyUsername '); // debugger exception here
Qry.SQL.Add(' AND UserPassword = :MyPassword '); // debugger exception here
Qry.SQL.EndUpdate;
Qry.Parameters.ParamByName('MyUsername').value := txtLogin.text;
Qry.Parameters.ParamByName('MyPassword').value := strmd5(txtPassword.text);
Qry.Open;
if Qry.Recordcount <> 1 then
begin
lblLoggedinAs.Text := format('Du er logget inn som: %s (%s)',[FieldByName('Username').AsString,FieldByName('UserEmailaddress').AsString]);
MainPageControl.ActivePageIndex := 1;
end
else
begin
txtPassword.Text := '';
txtPassword.SetFocus;
end;
finally
Qry.Free;
end;
end;
BTW, the nested withs are really ugly (let the holy war begin)
I will sometimes use with, but would never nest three levels! If you are, at least reduce the scope of with SQL so it ends before with Parameters.
Try setting an explicit datatype :
CreateSql.Parameters.ParamByName('MyUserName').DataType := ftString;
In my case, defining the parameters and assigning the query string before assigning the connection corrected the problem. The query executes successfully in both cases, but the TADOQuery component internally raises (and subsequently swallows) the EOleException noted in OP if the connection is assigned before the parameterized query.
//LADOQuery.Connection := LADOConnection; // Exception # LADOQuery.Text:=...
Param := LADOQuery.Parameters.AddParameter;
Param.Name := 'rid';
Param.DataType := ftFixedChar;
Param := LADOQuery.Parameters.AddParameter;
Param.Name := 'qd';
Param.DataType := ftLongWord;
LADOQuery.SQL.Clear;
LADOQuery.SQL.Text:='SELECT Val FROM table WHERE v1=:rid AND v2=:qd';
LADOQuery.Connection := LADOConnection; // OK!
I'm open to explanations as to why this is the case - nothing in the documentation seems to suggest a need for this order of operations.
The exception is raised in ADODB.pas in TADOCommand.AssignCommandText here
try
// Retrieve additional parameter info from the server if supported
Parameters.InternalRefresh;
where this branch is only followed if the TADOQuery is attached to a live connection. InternalRefresh performs :
if OLEDBParameters.GetParameterInfo(ParamCount,
PDBPARAMINFO(ParamInfo),
#NamesBuffer) = S_OK then
for I := 0 to ParamCount - 1 do
with ParamInfo[I] do
begin
// When no default name, fabricate one like ADO does
if pwszName = nil then
Name := 'Param' + IntToStr(I+1) else // Do not localize
Name := pwszName;
// ADO maps DBTYPE_BYTES to adVarBinary
if wType = DBTYPE_BYTES then wType := adVarBinary;
// ADO maps DBTYPE_STR to adVarChar
if wType = DBTYPE_STR then wType := adVarChar;
// ADO maps DBTYPE_WSTR to adVarWChar
if wType = DBTYPE_WSTR then wType := adVarWChar;
Direction := dwFlags and $F;
// Verify that the Direction is initialized
if Direction = adParamUnknown then Direction := adParamInput;
Parameter := Command.CommandObject.CreateParameter(Name, wType, Direction, ulParamSize, EmptyParam);
Parameter.Precision := bPrecision;
Parameter.NumericScale := ParamInfo[I].bScale;
// EOleException raised here vvvvvvvvv
Parameter.Attributes := dwFlags and $FFFFFFF0; //Mask out Input/Output flags
AddParameter.FParameter := Parameter;
end;
The problem definitely seems to be at the OLE level, probably because the MySQL ODBC driver does not support returning this information (or returns invalid information). The exception is raised behind the _Parameter interface when setting
Parameter.Attributes := dwFlags and $FFFFFFF0;
using what seem to be invalid values (dwFlags = 320 -> bits set above DBPARAMFLAGSENUM defined length) returned from GetParameterInfo. Exception handling for flow control seems the only option given that the interface does not provide any mechanism to check values before setting them (and triggering exceptions).
Update :
It turns out there is an open QC about this : http://qc.embarcadero.com/wc/qcmain.aspx?d=107267
BeginUpdate/EndUpdate pair is not adequate. Use AddParameter to add parameters explicity before assigning sql command. Like:
var
Qry : TADOQuery;
begin
Qry := CreateSQL;
try
with Qry.Parameters.AddParameter do
begin
Name := 'MyUsername';
DataType := ftString;
end;
with Qry.Parameters.AddParameter do
begin
Name := 'MyPassword';
DataType := ftString;
end;
Qry.SQL.BeginUpdate;
Qry.SQL.Add('SELECT');
Qry.SQL.Add(' *');
Qry.SQL.Add('FROM');
Qry.SQL.Add(' LisenswebUsers');
Qry.SQL.Add('WHERE UserName = :MyUsername '); // debugger exception here
Qry.SQL.Add(' AND UserPassword = :MyPassword '); // debugger exception here
Qry.SQL.EndUpdate;
...