Delphi 11 Front end to Cache Database
Hi,
Any examples please of connection a Delphi 11 Front end to a Cache database?
I can get it to connect but then when I try and view data it fails
4 fields in front end
SERVER = 127.0.0.1
PORT = 1972
NAMESPACE = DROP DOWN LIST (I SELECT "DEVELOP" FROM THE LIST
EDIT_CLASSNAME = Default value is Test (with maybe 3 fields just of random stuff)
procedure TFMAIN.BtnConnectClick(Sender: TObject);
var
ConnectString: string;
Success: Boolean;
Col,Row:Integer;
FieldName:array[0..10] of string;
begin
IF NAMESPACE.TEXT<='' THEN
BEGIN
SHOWMESSAGE('Please select a Namespace from the drop down list');
NAMESPACE.SETFOCUS;
EXIT;
END;
//Create instance of the TFactory object
Factory := TFactory.Create(nil);
//Establish connection with the server if there is no connection
if not Factory.IsConnected then
BEGIN
{
You can explicitly specify the connection string:
cn_iptcp - connection protocol
127.0.0.1 - Ip or sever name(Local Server)
[1972] - Port number
DEVELOP - Namespace
}
//ConnectString := 'cn_iptcp:127.0.0.1[1972]:DEVELOP';
//ConnectString := 'cn_iptcp:127.0.0.1[1972]:DEVELOP:User:Pass';
ConnectString := 'cn_iptcp:'+SERVER.TEXT+'['+PORT.TEXT+']:'+NAMESPACE.TEXT;
Success := Factory.Connect1(ConnectString);
END;
if not Success then
begin
ShowMessage('Could not connect!');
//Close the application if the connection fail.
//Application.Terminate;
BtnOpenObject.Enabled:=FALSE;
EXIT;
end;
outputMemo.Text := 'Connected to '+ConnectString;
BtnOpenObject.Enabled:=TRUE;
end;
;-------------------------------------------------------------------------------------------------------------
procedure TFMAIN.BtnOpenObjectClick(Sender: TObject);
var
sql:String;
begin
tmp:=EDIT_CLASSNAME.TEXT; //Angio.Episode1
IF tmp<='' THEN
BEGIN
SHOWMESSAGE('Enter an Object name');
EDIT_CLASSNAME.SETFOCUS;
EXIT;
END;
sql:='SELECT * FROM '+tmp;
TRY
//SQLQuery1.DatabaseName:='CacheDelphi';
//SQLCONNECTION1.ConnectionName:='CacheDelphi';
//-------------------------------------------------
//driver names can be found here
//C:\Windows\System32\odbcad32.exe
//InterSystems IRIS ODBC35
//InterSystems ODBC
//InterSystems ODBS35
//MySQL ODBC 8.0 ANSI Driver
//MySQL ODBC 8.0 Unicode Driver
//ODBS Driver 17for SQL Server
//SQL Server
//SQL Server Native Client 11.0
//-------------------------------------------------
SQLCONNECTION1.DriverName:='InterSystems ODBS35'; //DEVELOP
//SQLConnection1.Params.Values['Database'] := 'CacheDelphi';
//SQLConnection1.Params.Values['HostName'] := NAMESPACE.TEXT; //DEVELOP
SQLConnection1.Params.Values['User_Name'] := '_SYSTEM';
//SQLConnection1.Params.Values['Password'] := '';
SQLQuery1.CLOSE;
SQLQuery1.SQL.CLEAR;
SQLQuery1.SQL.ADD(sql);
SQLQuery1.OPEN;
except
on E: Exception do
outputMemo.Text := 'ERROR: ' + E.Message;
end;
// Show the results of the query in a TMemo control.
ShowSelectResults();
end;
;-------------------------------------------------------------------------------------------------------------
//show results in memo
procedure TFMAIN.ShowSelectResults();
var
names: TStringList;
i: Integer;
currentField: TField;
currentLine: string;
begin
if not SQLQuery1.IsEmpty then
begin
SQLQuery1.First;
names := TStringList.Create;
try
SQLQuery1.GetFieldNames(names);
while not SQLQuery1.Eof do
begin
currentLine := '';
for i := 0 to names.Count - 1 do
begin
currentField := SQLQuery1.FieldByName(names[i]);
currentLine := currentLine + ' ' + currentField.AsString;
end;
outputMemo.Lines.Add(currentLine);
SQLQuery1.Next;
end;
finally
names.Free;
end;
end;
end;
Jason
Comments
You appear to be mixing two different access methods in the same Delphi form:
TFactory.Connect1()is one connection mechanism using a connection string likecn_iptcp:127.0.0.1:DEVELOP. [2]SQLConnection1/SQLQuery1is a separate ODBC-based mechanism, where the driver must be configured and used correctly. [2]
Because your code connects with Factory.Connect1() but then runs SQLQuery1.OPEN through SQLConnection1, the successful Factory connection does not by itself make the SQL query work. [2]
A few points from your code stand out:
-
Your query is built as:
sql := 'SELECT * FROM ' + tmp;so
EDIT_CLASSNAMEmust contain something SQL can query as a table/class name. In your own example you mention values likeTestorAngio.Episode1; the code is expecting that string to be directly usable inSELECT * FROM .... [2] -
For the SQL part, you set only:
SQLConnection1.DriverName := 'InterSystems ODBS35'; SQLConnection1.Params.Values['User_Name'] := '_SYSTEM';but the shown code does not show the rest of the ODBC connection details being set before
SQLQuery1.OPEN. The commented lines also suggest uncertainty aboutDatabaseName,ConnectionName, andHostName. [2] -
Your own driver list comment shows possible driver names including:
InterSystems IRIS ODBC35InterSystems ODBCInterSystems ODBS35[2]
So the likely issue in the code shown is not the initial socket-style connection, but the incomplete or incorrect ODBC setup used by SQLConnection1 when you actually fetch data. [2]
Also, there is a related example from another discussion that suggests using SQL directly for external language access, for example:
insert into JASON.BikeDB (Make, Model) values (:make, :model)
and, if calling a class method instead, marking it with SqlProc and calling it as a stored procedure. [3]
This supports the idea that for a Delphi front end, SQL/stored procedure access is the simpler path than trying to mix object access and ODBC access in one flow. [3]
If you continue with ODBC-based access, there is an example showing the standard sequence for SQL access: open a connection, prepare a query, execute it, then fetch the result set. [4][5][6]
Important:
This article is intended only for developers who need to maintain existing legacy code. When developing new code to access the ODBC SQL Gateway programmatically, InterSystems strongly recommends use of the XDBC Gateway, which provides a much simpler and more maintainable way to accomplish the same tasks. [4][5][6]
Note:
This article assumes that you have significant experience using ODBC API calls — it is not intended to provide details on how to use ODBC functions. If you encounter any problems, you can monitor the SQL Gateway by enabling logging for both InterSystems IRIS and ODBC (see the "Logging and Environment Variables" chapter in Using the InterSystems ODBC Driver). [4][5][6]
Based on the code you posted, the safest conclusion is:
- your
Factory.Connect1()success only proves that one connection path works; [2] - your data retrieval is failing in the separate ODBC path; [2]
- you should use one access method consistently, and if using
SQLConnection1then fully configure that ODBC connection beforeSQLQuery1.OPEN. [2]
If you want, post the exact exception text from:
outputMemo.Text := 'ERROR: ' + E.Message;
because that message is what will identify whether the failure is driver selection, login, namespace/database selection, or invalid SQL/class name. [2]
Sources: