You are not logged in.
ok I tested the code and I saw that work if I try to open 2 file db3 from one server application,but does not work if I create a server program that opens a file on the server with port (eg 888) and I run it 2 times,how do I make a server program that opens multiple files if I do not know the number of the file that I want to open, I can add files to the server in a second time?
Thanks
ok Thanks
Thank you think using TSQLRestServerNamedPipe solve my problem?
Do you think that it is complicated to manage TSQLite3HttpServer for multiple instances?I mean, I could make the change or is too complicated?
Can I create multiple server types TSQLite3HttpServer in the same machine?
Should I create multiple instances of type server TSQLite3HttpServer with different ports (if I create multiple server instances with the same port "Es 888",Not working)
I would write an application that connects to multiple files residing on the server, but I do not know the port number I know the name of the file in the server.
What should I write?
Thanks
Do I must create a program that makes a server?
I can not send you a rar file?
How can I send you a sample of my program?
I do not use this configuration. Now I try to reduce my schedule for an example and try to send
Model := GetDatabaseModel;
Database:= TSQLRestClientDB.Create(Model, nil, filename, TSQLRestServerDB);
TSQLRestClientDB(Database).Server.CreateMissingTables(0);Sorry but maybe I have not explained,
I use sqlite Manager to view real-time changes in the temp table.
If I run the program and I execurte Database.Update (temp), and then I go to see sqlite Mangager I see new recorcd of temp.
Instead, if I run the program 2 times and one run an update, I see the change in sqlite manager and I can not see in the second program.
So I asked you how can I see the correct data from DB and you told me to use Database.UpdateFromServer ([temp], refreshed) but the data its not the same that I read by sqlite manager.Why?
Yes I can confirm, but it does not work, I created a table of relations between the user and the "temp" table and if I run the command
Database.UpdateFromServer ([temp.Users], refreshed) does not work
TSQLTemp = class(TSQLRecord)
private
...
fUsers: TSQLTempUsers;
published
...
property Users: TSQLTempUsers read fUsers;
end;
TSQLUser = class;
TSQLTempUsers = class(TSQLRecordMany)
private
fSource: TSQLTemp;
fDest: TSQLUser;
published
property Source: TSQLTemp read fSource;
property Dest: TSQLUser read fDest;
end;
// load list of Temp assigned to the given User
temp:= TSQLTemp.Create();
try
Database.UpdateFromServer ([temp.Users], refreshed);
temp.Users.SourceGet(Database, User.ID, clientsIds);
for i:= low(clientsIds) to high(clientsIds) do
begin
// find the client on the list (by ID)
for j:= 0 to CheckListBox1.Count -1 do
if Integer(CheckListBox1.Items.Objects[j]) = clientsIds[i] then
CheckListBox1.Checked[j]:= true;
end;
finally
temp.Free();
FreeAndNil(User);
end;Probably I did not understand how it works the command "Database.UpdateFromServer" with the "TSQLRecordMany" tables
To read the data from the sever usually write:
Model := GetDatabaseModel;
Database:= TSQLRestClientDB.Create(Model, nil, filename, TSQLRestServerDB);
TSQLRestClientDB(Database).Server.CreateMissingTables(0);
....
procedure TForm1.LoadTempForUser(const AUser: TSQLUser;
const AList: TStrings);
var
Temp: TSQLTemp;
fIds: TIntegerDynArray;
begin
if AUser.Temp.SourceGet(Database, AUser.ID, fIds) then
begin
Temp:= TSQLTemp.CreateAndFillPrepare(Database, fIds);
AList.BeginUpdate();
AList.Clear();
try
while Temp.FillOne do
AList.AddObject(Format('%s', [UTF8ToString(Temp.Name)]), Pointer(Temp.id));
finally
AList.EndUpdate();
FreeAndNil(Temp);
end;
end
else
AList.Clear();
end;
but if someone changes the values in the table (Es:"temp") in the server, I does not know how to update data on the client side.
ok thanks I think I understand
I would like to make a program in Delphi where more people use the same database "sqlite" simultaneously. What classes should I use? I'm forced to create a server?
I checked the save and re-read the tables is much slower, I was wrong to declare the type of table ,all tables are declared class (TSQLRecord).To save and share data with other users use globalClient.Update(XXX), where xxx is a class declared xxxx= class (TSQLRecord).
Thanks
1)first example of a connection without a server
program TestSqlite;
...
procedure InitClient(filename:String);
begin
Model:= CreateTestModel;
globalClient:= TSQLRestClientDB.Create(Model, CreateTestModel, filename, TSQLRestServerDB);
TSQLRestClientDB(globalClient).Server.CreateMissingTables(0);
end;
2)in the second example I created two programs, a client and a server
program TestSQliteServer;
uses
Forms,
FileTables in 'SQLite\FileTables.pas',
Unit2 in 'Unit2.pas' {Form1};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, SQLite3Commons, SQLite3, StdCtrls, FileTables;
type
TForm1 = class(TForm)
Label1: TLabel;
Button1: TButton;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormShow(Sender: TObject);
private
public
Model: TSQLModel;
Server: TSQLRestServerDB;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Close;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Model := CreateTestModel;
Server := TSQLRestServerDB.Create(Model,'Test.db3');
Server.CreateMissingTables(0);
if Server.ExportServerNamedPipe('03') then
Caption := format('%s - %s Connected',[Caption,Server.DB.FileName ]);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Server.Free;
Model.Free;
end;
procedure TForm1.FormShow(Sender: TObject);
begin
Label1.Caption := Caption;
end;
////////
program TestSQliteClient;
...
InitClient('\\severTest\pipe\Sqlite3_03');
end;
procedure InitClient(filename:String);
begin
Model:= CreateTestModel;
globalClient:= TSQLRestClientURINamedPipe.Create(Model,filename); //for connection to server "severTest"
TSQLRestClientDB(globalClient).Server.CreateMissingTables(0);
end;
ok thanks, I look forward to new developments on
Hi, I would like to use your framework but I would be sure to use it with other databases, where can I find documentation, or better yet any examples?
Thanks I put the flag true to globalClient.ForceBlobTransfert but my problem was another, I had to add WideString otherwise gave me error invalid character
write
Atemp.XMLObject := XMLQVObjects.XML;
read
FXmlDoc:= NewXMLDocument;
FXMLDoc.LoadFromXML(widestring(ATemp.XMLObject));
.....
procedure InitClient(filename:String);
begin
Model:= CreateNuvolaModel;
globalClient:= TSQLRestClientDB.Create(Model, CreateNuvolaModel, filename, TSQLRestServerDB);
TSQLRestClientDB(globalClient).Server.CreateMissingTables(0);
globalClient.ForceBlobTransfert := true;
end;
When I go to read the field value is no longer compatible with xml. I have declared a field of type TSQLRawBlob.
See the following example:
TSQLTemp = class(TSQLRecord)
private
fXMLObject:TSQLRawBlob;
...
published
property XMLObject:TSQLRawBlob read fXMLObject write fXMLObject;
...
end;
...create record
var
temp:= TSQLTemp;
FXmlDoc: IXMLDocument;
begin
try
temp:= TSQLTemp.Create;
FXmlDoc:= NewXMLDocument;
FXMLDoc.LoadFromFile(sfilename);
temp.XMLObject := FXMLDoc.XML.Text;
globalClient.Add(temp, true);
finally
FreeAndNil(temp);
end;
end;
...read record
function TForm1.LoadTemplate(const ATempID: integer): TSQLTemp;
var
temp:= TSQLTemp;
FXmlDoc: IXMLDocument;
begin
try
temp:= TSQLTemp.Create(globalClient, ATempID);
FXmlDoc:= NewXMLDocument;
FXMLDoc.LoadFromFile(Temp.XMLObject); //here I can not read a xml
finally
FreeAndNil(temp);
end;
end;
Of course, I have to compile a list of items of SQLTemp class that belong to a one user (SQLUser) and a one role (SQLUserRole), if I apply the code I have written above only see the items in the second filter, because the array fIDs is overwritten . What should I write to obtain the sum of the two results?
I used your example "Synops-sqlite-demo-read-only" and I added a single class TSQLTemp "then I wanted to clump them elements of subclasses User.Temps Role.Temps and where the role is the role of the user. I wrote this function:
procedure TForm1.LoadTemplatesForUserAndRole(const AUser: TSQLUser);
var
Temp: TSQLTemp;
fIds: TIntegerDynArray;
ARole: TSQLUserRole;
begin
AUser.Temps.SourceGet(globalClient, AUser.ID, fIds);
AUser.Roles.FillMany(globalClient, AUser.ID);
while AUser.Roles.FillOne do
begin
if AUser.Roles.Dest <> nil then
try
ARole:= TSQLUserRole.Create(globalClient, integer(AUser.Roles.Dest));
//But at this point is overwritten Fids
ARole.Temps.SourceGet(globalClient, ARole.ID, fIds);
finally
FreeAndNil(ARole);
end;
end;
Temp:= TSQLTemp.CreateAndFillPrepare(globalClient, fIds);
DisplayTempDataset(Temp);
end;
I posted the correct version of the class TSQLTemp = class (TSQLRecord)
TSQLTemp = class(TSQLRecord)
private
fCodice: Integer;
fName : RawUTF8;
fUsers: TSQLTempUsers;
fRoles: TSQLTempRoles;
published
property Codice: Integer read fCodice write fCodice;
property Name: RawUTF8 read fName write fName;
property Users: TSQLTempUsers read fUsers;
property Roles: TSQLTempRoles read fRoles;
end;
I Don't want to take advantage of your kindness but I have another doubt.
I created a class TSQLTemp connected to two other classes, if I wanted to run the merge of the two classes what to do?.
User.Temps + User.Roles.Temps = All the elements of a single user "temp" and "temp" all the elements of all the roles of the same single user
unit FileTables;
interface
uses
SynCommons,
SQLite3Commons;
type
TSQLTempUsers = class;
TSQLTempRoles = class;
TSQLTemp = class(TSQLRecord)
private
fCodice: Integer;
fName : RawUTF8;
published
property Codice: Integer read fCodice write fCodice;
property Name: RawUTF8 read fName write fName;
end;
TSQLUser = class;
TSQLTempUsers = class(TSQLRecordMany)
private
fSource: TSQLTemp;
fDest: TSQLUser;
published
property Source: TSQLTemp read fSource;
property Dest: TSQLUser read fDest;
end;
TSQLUserRole = class(TSQLRecord)
private
fRoleName: RawUTF8;
fTemps: TSQLTempRoles;
public
// create standard roles: admin & user
class procedure CreateStandardRoles(const ADatabase: TSQLRest);
published
property RoleName: RawUTF8 read fRoleName write fRoleName;
property Temps: TSQLTempRoles read fTemps;
end;
TSQLUserRoles = class(TSQLRecordMany)
private
fValidUntil: TTimeLog;
fSource: TSQLUser;
fDest: TSQLUserRole;
published
property ValidUntil: TTimeLog read fValidUntil write fValidUntil;
property Dest: TSQLUserRole read fDest;
property Source: TSQLUser read fSource;
end;
TSQLTempRoles = class(TSQLRecordMany)
private
fSource: TSQLTemp;
fDest: TSQLUserRole;
published
property Source: TSQLTemp read fSource;
property Dest: TSQLUserRole read fDest;
end;
// user of our system
TSQLUser = class(TSQLRecord)
private
fRoles: TSQLUserRoles;
fLogin, fPassword: RawUTF8;
fName : RawUTF8;
fSubName: RawUTF8;
fTemps: TSQLTempUsers;
procedure SetPassword(const APwd: RawUTF8);
public
function HasRole(const ARoleName: RawUTF8; const ARoleID: integer = -1): boolean; overload;
// returned aRowID is an ID of row in PIVOT TABLE !!!
// so that we can access additional data stored in pivot connection
function HasRole(const ARoleName: RawUTF8; const ARoleID: integer; var ARowID: integer): boolean; overload;
// returns 0 on fail, UserID on success
class function SignIn(const ALogin, APassword: RawUTF8): Integer;
// counts all users
// -1 on error
class function GetCount(): integer;
published
property Roles: TSQLUserRoles read fRoles write fRoles;
property Name: RawUTF8 read fName write fName;
property SubName: RawUTF8 read fSubName write fSubName;
property Login: RawUTF8 read fLogin write fLogin;
property Password: RawUTF8 read fPassword write SetPassword;
property Temps: TSQLTempUsers read fTemps;
end;
Thanks! now the code is as follows:
constructor TcxCustomDataSource.Create(const ATemplate: TSQLTemplate);
begin
inherited Create;
Dest := ATemp;
end;
destructor TcxCustomDataSource.Destroy;
begin
inherited Destroy;
end;
procedure TcxCustomDataSource.DeleteRecord(
ARecordHandle: TcxDataRecordHandle);
begin
//T.Delete(Integer(ARecordHandle));
end;
function TcxCustomDataSource.GetRecordCount: Integer;
begin
Result := Dest.FillTable.RowCount;
end;
function TcxCustomDataSource.GetValue(ARecordHandle: TcxDataRecordHandle;
AItemHandle: TcxDataItemHandle): Variant;
var
col : TcxGridColumn;
row : Integer;
// Dest : TSQLTemp;
// id : Integer;
begin
col := TcxGridColumn(DataController.GetItem(integer(AItemHandle)));
row := Integer(ARecordHandle)+1;
try
// id := fTable.IDColumnHiddenValue(row);
// Dest := TSQLTemp.Create;
// Dest.FillPrepare(fTable);
Dest.FillRow(row);
case col.Tag of
IndexOfName:
Result := Dest.Name;
IndexOfDesc:
Result := Dest.Desc;
IndexOfID:
Result := Dest.ID;
end;
finally
// FreeAndNil(Dest);
end;
end;
procedure TcxCustomDataSource.SetValue(ARecordHandle: TcxDataRecordHandle;
AItemHandle: TcxDataItemHandle; const AValue: Variant);
var
col : TcxGridColumn;
row : Integer;
// Dest : TSQLTemp;
// id : Integer;
refreshed :Boolean;
begin
col:= TcxGridColumn(DataController.GetItem(integer(AItemHandle)));
row := Integer(ARecordHandle)+1;
try
// Dest := TSQLTemp.Create;
// Dest.FillPrepare(fTable);
Dest.FillRow(row);
if assigned(Dest) then
begin
case col.Tag of
IndexOfName:
Dest.Name := AValue ;
IndexOfDesc:
Dest.Desc := AValue ;
IndexOfID:
Dest.ID := AValue ;
end;
globalClient.Update(Dest);
globalClient.UpdateFromServer([Dest.FillTable],refreshed); // this is to refresh the grid content
end;
finally
// FreeAndNil(Dest);
end;
end;
Thanks for "fTable.IDColumnHiddenValue (riga) "
ok maybe now, I understand how it works,
but then I ask you is it right to call for each GetValue the method : Dest.FillPrepare ( fTable) as an example, or is it better to create it only once in the function ?
function TcxCustomDataSource.GetValue(ARecordHandle: TcxDataRecordHandle;
AItemHandle: TcxDataItemHandle): Variant;
....
begin
try
Dest: = TSQLTemplate.Create;
Dest.FillPrepare ( fTable)
Dest.FillRow (row)
...
finally
FreeAndNil(Dest);
end;
end;
function TcxCustomDataSource.GetValue(ARecordHandle: TcxDataRecordHandle;
AItemHandle: TcxDataItemHandle): Variant;
var
col : TcxGridColumn;
row : Integer;
Dest : TSQLTemplate;
// id : Integer;
begin
col := TcxGridColumn(DataController.GetItem(integer(AItemHandle)));
row := Integer(ARecordHandle)+1;
try
// id := fTable.IDColumnHiddenValue(row);
Dest := TSQLTemp.Create;
Dest.FillPrepare(fTable);
Dest.FillRow(row);
case col.Tag of
IndexOfNome:
Result := Dest.Name;
IndexOfDesc:
Result := Dest.Desc;
IndexOfID:
Result := Dest.ID;
end;
finally
FreeAndNil(Dest);
end;
end;
procedure TcxCustomDataSource.SetValue(ARecordHandle: TcxDataRecordHandle;
AItemHandle: TcxDataItemHandle; const AValue: Variant);
var
col : TcxGridColumn;
row : Integer;
Dest : TSQLTemp;
// id : Integer;
refreshed :Boolean;
begin
col:= TcxGridColumn(DataController.GetItem(integer(AItemHandle)));
row := Integer(ARecordHandle)+1;
try
Dest := TSQLTemp.Create;
Dest.FillPrepare(fTable);
Dest.FillRow(row);
if assigned(Dest) then
begin
case col.Tag of
IndexOfNome:
Dest.Name := AValue ;
IndexOfDesc:
Dest.Desc := AValue ;
IndexOfID:
Dest.ID := AValue ;
end;
globalClient.Update(Dest);
globalClient.UpdateFromServer([fTable],refreshed); // this is to refresh the grid content
end;
finally
FreeAndNil(Dest);
end;
end;
I ask this because in the quantum grid getValue procedure is launched for each column. Thanks
Thanks now it works. But what is the best way between the first and the following example, to work with a quantumgrid
function TcxCustomDataSource.GetRecordCount: Integer;
begin
// Result := T.FillTable.RowCount;
Result := fTable.RowCount;
end;
function TcxCustomDataSource.GetValue(ARecordHandle: TcxDataRecordHandle;
AItemHandle: TcxDataItemHandle): Variant;
var
col : TcxGridColumn;
row : Integer;
Dest : TSQLTemp;
id : Integer;
begin
col := TcxGridColumn(DataController.GetItem(integer(AItemHandle)));
row := Integer(ARecordHandle)+1;
try
id := fTable.GetAsInteger(row,fTable.FieldIndex('ID'));
Dest := TSQLTemp.Create(globalClient, id);
case col.Tag of
IndexOfName:
Result := Dest.Name;
...
end;
finally
FreeAndNil(Dest);
end;
end;
procedure TcxCustomDataSource.SetValue(ARecordHandle: TcxDataRecordHandle;
AItemHandle: TcxDataItemHandle; const AValue: Variant);
var
col : TcxGridColumn;
row : Integer;
Dest : TSQLTemp;
id : Integer;
begin
col:= TcxGridColumn(DataController.GetItem(integer(AItemHandle)));
row := Integer(ARecordHandle)+1;
try
id := fTable.GetAsInteger(row,fTable.FieldIndex('ID'));
Dest := TSQLTemp.Create(globalClient, id);
case col.Tag of
IndexOfName:
Dest.Name := AValue ;
...
end;
globalClient.Update(Dest);
end;
finally
FreeAndNil(Dest);
end;
end;
Hi,
I would like to use fillprepare() and FillRow() to read / add / delete / edit data from a table.I post an example below:
var
T: TSQLTemp;
row : Integer;
begin
T:= TSQLTemplate.CreateAndFillPrepare(globalClient, '');
row := 1;
T.FillRow(row);
Showmessage(T.Name) ; // the value is "YYY";
//I set new value and execute update
T.Name := 'xxxxx';
globalClient.Update(T);
//I move to next record;
row := 2;
T.FillRow(row);
Showmessage(T.Name) ; // the value is "PPP";
//now if I read the value of the first row (I use FillRow to move between the records)
row := 1;
T.FillRow(row);
Showmessage(T.Name) ; // the value is "YYY" and not "XXXX"; Why?
thanks and sorry for my English