#151 Re: mORMot 1 » How to create a MSSQL Database from TSQLModel? » 2011-11-23 11:25:26

ok thanks

now I have these tables and when I Server.CreateMissingTables in SQLite function in MSSQL and an exception occurs when I create the user table or role etc.. I think it's because it refers to the group of roles and these tables do not exist yet.

I can create tables "TSQLRecordMany" and if you like I have to write code?thanks

type

  TSQLUser =Class;
  TSQLRole =Class;
  TSQLGruppo =Class;
  TSQLGroupRoles = class;
  TSQLUserGroups = Class;
  TSQLUserRoles = class;

  TSQLFile = class(TSQLRecordExternal)// class(TSQLRecordSigned)
  private
    Check:Boolean;
  public
    fName: RawUTF8;
    fModified: TTimeLog;
    fCreated: TTimeLog;
    fPicture: TSQLRawBlob;
    fKeyWords: RawUTF8;
    fLabel :RawUTF8;
    fImageIndex: Integer;
    function CheckValues(Reference: TSQLRecord): boolean;virtual;
    function CopyFrom(ARec: TSQLRecord): TSQLRecord;
    procedure CopyTo(var ARec:TSQLRecord);
  published
    property Name: RawUTF8 read fName write fName;
    property Created: TTimeLog read fCreated write fCreated;
    property Modified: TTimeLog read fModified write fModified;
    property Picture: TSQLRawBlob read fPicture write fPicture;
    property KeyWords: RawUTF8 read fKeyWords write fKeyWords;
//    property SignatureTime;
//    property Signature;

    property Label_: RawUTF8 read fLabel write fLabel;
    property ImageIndex: Integer read FImageIndex write FImageIndex;
  end;

  
  TSQLUser = class(TSQLFile)
  private
    fRoles: TSQLUserRoles;
    fLogin, fPassword: RawUTF8;
    fSubName: RawUTF8;
    fGroups: TSQLUserGroups;
  public
    property Roles: TSQLUserRoles read fRoles write fRoles;
    property Groups: TSQLUserGroups read fGroups write fGroups;

  published
    property Login: RawUTF8 read fLogin write fLogin;
    property Password: RawUTF8 read fPassword write SetPassword;
    property SubName: RawUTF8 read fSubName write fSubName;
  end;

  TSQLGruppo = class(TSQLFile)
  private
    fUsers: TSQLUserGroups;
    fRoles: TSQLGroupRoles;
  public

  published
    property Users: TSQLUserGroups read fUsers write fUsers;
    property Roles: TSQLGroupRoles read fRoles write fRoles;
  end;


  TSQLRole = class(TSQLFile)
  private
    fUsers: TSQLUserRoles;
    fGroups: TSQLGroupRoles;
  public

  published
    property Users: TSQLUserRoles read fUsers write fUsers;
    property Groups: TSQLGroupRoles read fGroups write fGroups;
  end;
 
  TSQLUserGroups = class(TSQLRecordMany)
  private
    fValidUntil: TTimeLog;
    fSource: TSQLUser;
    fDest: TSQLGruppo;
  published
    property Source: TSQLUser read fSource;
    property Dest: TSQLGruppo read fDest;
  end;

  TSQLUserRoles = class(TSQLRecordMany)
  private
    fValidUntil: TTimeLog;
    fSource: TSQLUser;
    fDest: TSQLRole;
  published
    property ValidUntil: TTimeLog read fValidUntil write fValidUntil;
    property Source: TSQLUser read fSource;
    property Dest: TSQLRole read fDest;
  end;

#152 Re: mORMot 1 » How to create a MSSQL Database from TSQLModel? » 2011-11-23 08:27:10

Sorry but I am not yet clear. I had to insert this line "fClient: = TSQLRestClientDB.Create (Model, nil, 'test.db3', TSQLRestServerDB)," because the tables were created in MSSQL. I do not understand why I need to create a db3 "test.db3" and then work with MSSQL. But where the data are saved?


constructor TFileServer.Create(const ServerName,SeverPort: AnsiString;const aFilename: AnsiString);
var
    i:Integer;
    fClient: TSQLRestClientDB;
    fConnection: TSQLDBConnectionProperties;
    Start, Updated: TTimeLog;
begin
  try


   Props := TOleDBMSSQLConnectionProperties.Create('SQL2008\SQL2008',',MyDB','','');
   inherited Create(CreateFileModel(self));

   for i := 0 to high(Model.Tables) do
      VirtualTableExternalRegister(Model, TSQLRecordExternalClass(Model.Tables[i]),Props,'');



  try
    fClient := TSQLRestClientDB.Create(Model,nil,'test.db3',TSQLRestServerDB);
    Start := fClient.ServerTimeStamp;
    fClient.Server.StaticVirtualTableDirect := StaticVirtualTableDirect;
    fClient.Server.CreateMissingTables;
  finally
    fClient.Free;
  end;

...

thanks

#153 Re: mORMot 1 » How to create a MSSQL Database from TSQLModel? » 2011-11-22 15:39:40

If I derive classes from TSQLRecordExternal means I have to modify the code written for the model, I had understood that it not necessary to modified the original classes

TSQLFile = class(TSQLRecordSigned)   modified to TSQLFile = class(TSQLRecordExternal)
  private 
...
end
 // user of our system
  TSQLUser = class(TSQLFile) 
  private
...
end
//VirtualTableExternalRegister(fModel,TSQLRecordPeopleExt,fConnection,'PeopleExternal');

function CreateFileModel(Owner: TSQLRest): TSQLModel;
var Classes: array[0..high(FileTabs)] of TSQLRecordClass;
    i: integer;
begin

  for i := 0 to high(FileTabs) do
    Classes[i] := FileTabs[i].Table;

  Model := TSQLModel.Create(Classes);
  Model.Owner := Owner;
  Model.SetEvents(TypeInfo(TFileEvent));
  Result := Model;
end;


constructor TFileServer.Create(const ServerName,SeverPort: AnsiString;const aFilename: AnsiString);
var
 i :Integer;
begin
  try

  writeln(format('file server is %s',[aFilename]));
  inherited Create(CreateFileModel(self),aFilename);

 {$ifdef MSSQL}
   Props := TOleDBMSSQLConnectionProperties.Create('SQL2008\SQL2008',MyDB','','');
   inherited Create(CreateFileModel(self))
   for i := 0 to high(Model.Tables) do
      VirtualTableExternalRegister(Model, Model.Tables[i],Props,'');
  {$endif}

  CreateMissingTables(0); // ExeVersion.Version.Version32);
  Server := TSQLite3HttpServer.Create(SeverPort,[self],ServerName);


  finally

  end;

end;

way is it correct?  or the following code is not needed?

...
for i := 0 to high(Model.Tables) do
      VirtualTableExternalRegister(Model, Model.Tables[i],Props,'');
...

thanks

#154 Re: mORMot 1 » How to create a MSSQL Database from TSQLModel? » 2011-11-22 14:12:41

Sorry,

I read the documentation but I have not found a consistent example to make me understand how to implement the connection using MSSQL and my model without adding new classes.
I wrote the following routine that uses the server to connect to SQLite files, what should I add to make sure that the tables are created depending on the model?


constructor TFileServer.Create(const ServerName,SeverPort: AnsiString;const aFilename: AnsiString);

begin
  try

  writeln(format('file server is %s',[aFilename]));
  inherited Create(CreateFileModel(self),aFilename);
  CreateMissingTables(0); // ExeVersion.Version.Version32);
  Server := TSQLite3HttpServer.Create(SeverPort,[self],ServerName);

  {$ifdef MSSQL}
   Props := TOleDBMSSQLConnectionProperties.Create('SQL2008\SQL2008',MyDB','','');
   inherited Create(CreateFileModel(self))
   
  {$endif}

  finally

  end;



end;

thanks

#155 Re: mORMot 1 » How to create a MSSQL Database from TSQLModel? » 2011-11-22 11:37:06

I forgot to tell you that I work in a network is not the Internet, change anything?

#156 Re: mORMot 1 » How to create a MSSQL Database from TSQLModel? » 2011-11-22 11:31:07

ok thanks, before, I try to connect to MSSQL and then I will do all the tests that you suggested

#157 mORMot 1 » How to create a MSSQL Database from TSQLModel? » 2011-11-22 10:35:36

corchi72
Replies: 18

I created a client \ server by using it your own framework.
I have used the SQLite as database server, but the client operations are too slow, now I want to migrate to MSSQL and I read that it's possible.
I ask if there is a procedure that automatically creat all the tables in MSSQ ( with "CreateMissingTables") or I have to map every single class of my model with the MSSQL tables?
I only found this example:

// !  Props := TOleDBMSSQLConnectionProperties.Create('.\SQLEXPRESS','AdventureWorks2008R2','','');
// !  Model := TSQLModel.Create([TSQLCustomer],'root');
// !  VirtualTableExternalRegister(Model,TSQLCustomer,Props,'Sales.Customer');

Thanks corchi 72

#158 mORMot 1 » Error compiling SynTaskDialog.pas » 2011-11-02 13:37:03

corchi72
Replies: 1

Filling this with "USETMSPACK" I have an error in the unit SynTaskDialog, I moved the directive "{$ endif} USETMSPACK" after the definition "TTaskDialogEx" and two other points.

Thanks corchi72

#159 mORMot 1 » How do you declare a foreign key? » 2011-10-28 08:24:11

corchi72
Replies: 1

Hello, I have a question to ask yourself, I have a class that has TSQLQVW a property called "connection" that refers to another class TSQLConnection, what is the right way to write the class TSQLQVW not have to go around I have written below.
Is there another solution?
I did not want to use the usual class "TSQLRecordMany" to create the relationship because it is a type of relationship one to many but just a one to one

  TSQLQvwConnections= class(TSQLRecordMany)
  private
    fSource: TSQLQvw;
    fDest: TSQLConnection;
  published
    property Source:  TSQLQvw read fSource;
    property Dest: TSQLConnection read fDest;
  end;

This is the code that I implemented and it works but I think it's the right solution

 
  TSQLConnection = class(TSQLFile)
  private
    fOwner: RawUTF8;
    fEnabled: boolean;
    fConnectionString:RawUTF8;
 ...  
  published

    property Owner: RawUTF8 read fOwner write fOwner;
    property Enabled: boolean read fEnabled write fEnabled;
    property ConnectionString:RawUTF8 read fConnectionString write fConnectionString;
  end;
  
  
  
  TSQLQvw = class(TSQLFile)
  private
    fOwner: RawUTF8;
    fEnabled: boolean;
  ...
    fConnection: TSQLConnection;
    FConnectionID: Integer;
    procedure SetConnectionID(const Value: Integer);
    function GetConnection: TSQLConnection;
    procedure SetConnection(const Value: TSQLConnection);
    property Connection: TSQLConnection read GetConnection write SetConnection;
   published

    property Owner: RawUTF8 read fOwner write fOwner;
    property Enabled: boolean read fEnabled write fEnabled;
   ...
    property ConnectionID:Integer read FConnectionID write SetConnectionID;
  end; 
  
  var
  Model: TSQLModel;
  currentClient : TSQLRestClientUri;
  
  ....
  
 implementation 
  
  
procedure TSQLQvw.SetConnection(const Value: TSQLConnection);
begin
  FConnectionID := Value.ID;
end;

procedure TSQLQvw.SetConnectionID(const Value: Integer);
begin
  FConnectionID := Value;
end;


function TSQLQvw.GetConnection: TSQLConnection;
begin
  result := TSQLConnection.Create(currentClient,FConnectionID);
end; 

#160 Re: mORMot 1 » I want to write a query with the parameters but I don't know to do » 2011-10-19 10:29:18

I developed two solutions and the second is faster than a second, but I also decided to include the first solution in my program because it is in line with your framework, and is more understandable and maintainable.



1) solution:

function TSQLUser.LoadQvws(ClientDB: TSQLRestClientUri): TSQLQvw;
var
 fIds,fIds4: TIntegerDynArray;
 fIdsUser,fIdsGroup,fIdsRole,fIdsGroupRoles:TIntegerDynArray;
 i,j:Integer;

 AGroupQvws: TSQLGroupQvws;
 ARoleQvws : TSQLRoleQvws;
begin
  result := nil;
  SetLength(fIds4,0);


 fGroups.DestGet(ClientDB, self.ID, fIdsGroup);
  AGroupQvws := TSQLGroupQvws.CreateAndFillPrepare(ClientDB,IntegerDynArrayToCSV(fIdsGroup,length(fIdsGroup),'Source IN (',')'));
  while AGroupQvws.FillOne do
     AddInteger(fIds4,AGroupQvws.Dest.ID ,true);
  AGroupQvws.FillClose;

  fRoles.DestGet(ClientDB, self.ID, fIdsRole);
  fIdsGroupRoles:=ReadGroupRoles(ClientDB,fIdsGroup);
  AddSortedIntegerArray(fIdsGroupRoles,fIdsRole);
  ARoleQvws := TSQLRoleQvws.CreateAndFillPrepare(ClientDB,IntegerDynArrayToCSV(fIdsRole,length(fIdsRole),'Source IN (',')'));
  while ARoleQvws.FillOne do
     AddInteger(fIds4,ARoleQvws.Dest.ID ,true);
  ARoleQvws.FillClose;

  fQvws.DestGet(ClientDB, self.ID, fIds);
  for I := 0 to Length(fIds) - 1 do
  begin
     AddInteger(fIds4,fIds[i] ,true);
  end;


  if Length(fIds4)>0 then
  begin
     SetLength(fIds,Length(fIds4));
     CopyAndSortInteger(Pointer(fIds4),Length(fIds4),fIds);
     result := TSQLQvw.CreateAndFillPrepare(ClientDB, fIds);
  end;


end;

2) solution:

function TSQLUser.LoadQvws(ClientDB: TSQLRestClientUri): TSQLQvw;
var
 fIds,fIds4: TIntegerDynArray;
 fIdsUser,fIdsGroup,fIdsRole,fIdsGroupRoles:TIntegerDynArray;
 i,j:Integer;

 fSQLSelect: RawUTF8;
 fSQLWhereGroups: RawUTF8;
 fSQLLeftJoinGroups: RawUTF8;
 fSQLWhereRoles: RawUTF8;
 fSQLLeftJoinRoles: RawUTF8;
 fSQLWhereUser: RawUTF8;
 fSQLLeftJoinUser: RawUTF8;

 fSQLWhere: RawUTF8;
 fSQLLeftJoin: RawUTF8;
 aTable: TSQLTable;

begin 
  fIdsGroup := ReadGroups(ClientDB);
  if Length(fIdsGroup)>0 then
  begin
    fSQLLeftJoinGroups :=  format('left join %s on %s.Dest= %s.ID',[TSQLGroupQvws.SQLTableName,TSQLGroupQvws.SQLTableName,TSQLQvw.SQLTableName]);
    fSQLWhereGroups := format('%s.%s',[TSQLGroupQvws.SQLTableName,IntegerDynArrayToCSV(fIdsGroup,length(fIdsGroup),'Source IN (',')')]);
    fSQLWhere := fSQLWhereGroups;
    fSQLLeftJoin := fSQLLeftJoinGroups;
  end;
  fIdsRole := ReadRoles(ClientDB);
  fIdsGroupRoles:=ReadGroupRoles(ClientDB,fIdsGroup);
  AddSortedIntegerArray(fIdsGroupRoles,fIdsRole);
  if Length(fIdsRole)>0 then
  begin
    fSQLLeftJoinRoles :=  format('left join %s on %s.Dest= %s.ID',[TSQLRoleQvws.SQLTableName,TSQLRoleQvws.SQLTableName,TSQLQvw.SQLTableName]);
    fSQLWhereRoles  := format('%s.%s',[TSQLRoleQvws.SQLTableName,IntegerDynArrayToCSV(fIdsRole,length(fIdsRole),'Source IN (',')')]);
    if fSQLWhere<>'' then  fSQLWhere := fSQLWhere + ' or ';
    fSQLWhere := fSQLWhere +  fSQLWhereRoles;
    if fSQLLeftJoin<>'' then fSQLLeftJoin := fSQLLeftJoin + ' ';
    fSQLLeftJoin := fSQLLeftJoin +fSQLLeftJoinRoles;
  end;

  fQvws.DestGet(ClientDB, self.ID, fIds);
  if Length(fIds)>0 then
  begin
    fSQLLeftJoinUser :=  format('left join %s on %s.Dest= %s.ID',[TSQLUserQvws.SQLTableName,TSQLUserQvws.SQLTableName,TSQLQvw.SQLTableName]);
    fSQLWhereUser  := format('%s.Source = %d',[TSQLUserQvws.SQLTableName,self.ID]);
    if fSQLWhere<>'' then  fSQLWhere := fSQLWhere + ' or ';
    fSQLWhere := fSQLWhere +  fSQLWhereUser;
    if fSQLLeftJoin<>'' then fSQLLeftJoin := fSQLLeftJoin + ' ';
    fSQLLeftJoin := fSQLLeftJoin +fSQLLeftJoinUser;
  end;

  fSQLSelect := format('Select %s from %s %s where %s group by %s.ID', [TSQLQvw.RecordProps.SQLTableSimpleFields[true,true],TSQLQvw.SQLTableName,fSQLLeftJoin,fSQLWhere,TSQLQvw.SQLTableName]);
  aTable := ClientDB.ExecuteList([TSQLQvw],fSQLSelect);
  Result := TSQLQvw.Create;
  if aTable = nil then exit;
  Result.FillPrepare(aTable);

This function is used in both solutions

function TSQLUser.ReadGroupRoles(ClientDB: TSQLRestClientUri;fIdsGroup:TIntegerDynArray):TIntegerDynArray;
var
  fIdsRole:TIntegerDynArray;
  AGruppo:TSQLGruppo;
  AGroupRoles:TSQLGroupRoles;
begin
  SetLength(fIdsRole,0);

  AGroupRoles := TSQLGroupRoles.CreateAndFillPrepare(ClientDB,fIdsGroup);
  while AGroupRoles.FillOne do
     AddInteger(fIdsRole,AGroupRoles.Dest.ID,false);

  result := fIdsRole
end;

Thanks corchi

#161 mORMot 1 » I want to write a query with the parameters but I don't know to do » 2011-10-18 15:38:15

corchi72
Replies: 2

How to convert this Query in a format string (fSQLWhere) for to create a TSQLQvw.CreateAndFillPrepare(ClientDB, fSQLWhere) correctly.
I have to get a resultset of TSQLQvw

 TSQLGroupRoles = class(TSQLRecordMany)
  private
    fSource: TSQLGruppo;
    fDest: TSQLRole;
  published
    property Source: TSQLGruppo read fSource;
    property Dest: TSQLRole read fDest;
  end;

  TSQLUserQvws = class(TSQLRecordMany)
  private
    fSource: TSQLUser;
    fDest: TSQLQvw;
  published
    property Source:  TSQLUser read fSource;
    property Dest: TSQLQvw read fDest;

  end;

  TSQLRoleQvws = class(TSQLRecordMany)
  private
    fSource: TSQLRole;
    fDest: TSQLQvw;
  published
    property Source: TSQLRole read fSource;
    property Dest: TSQLQvw read fDest;
  end;

  TSQLGroupQvws = class(TSQLRecordMany)
  private
    fSource: TSQLGruppo;
    fDest: TSQLQvw;
  published
    property Source: TSQLGruppo read fSource;
    property Dest: TSQLQvw read fDest;
  end;

 TSQLQvw = class(TSQLFile)
  private
...
 published

    property Users: TSQLUserQvws read fUsers;
    property Groups: TSQLGroupQvws read fGroups;
    property Roles: TSQLRoleQvws read fRoles;
end;

function TSQLUser.LoadQvws(ClientDB: TSQLRestClientUri): TSQLQvw;
var
fIdsQvw,fIdsGroup,fIdsRole:TIntegerDynArray;
begin

  fQvws.DestGet(ClientDB, self.ID, fIdsQvw);
  fGroups.DestGet(ClientDB, self.ID, fIdsGroup);
  fRoles.DestGet(ClientDB, self.ID, fIdsRole);

result := TSQLQvw.CreateAndFillPrepare(ClientDB,
"
SELECT Qvw.ID,Name,Description FROM Qvw
left join GroupQvws
on GroupQvws.Dest= Qvw.ID
left join RoleQvws
on RoleQvws.Dest= Qvw.ID
WHERE GroupQvws.Source IN (2 (=> fIdsGroup) ) or RoleQvws.Source IN (1,2 (=> fIdsRole) ) or Qvw.ID IN (30,33  (=> fIdsQvw))
"
I want to write this query with the parameters but I don't know to do it:
SELECT %.ID,Name FROM %
left join %
on %.Dest= %.ID
left join %
on %.Dest= %.ID
%.Source IN (?) or %.Source IN (?) or %.ID IN (?), not with the values

end;

Thanks corchi

#163 Re: mORMot 1 » Why did you decide to keep the record of relationships and set val "0" » 2011-09-22 14:39:46

for one table I have three or four tables of relationships,

each table is related to the tables of the user roles and groups

#164 mORMot 1 » Why did you decide to keep the record of relationships and set val "0" » 2011-09-22 13:51:17

corchi72
Replies: 8

Why did you decide to keep the record of relationships and set the value to 0 rather than deleting the record, remain a lot of unnecessary records of relationships
I have written

function TSQLRestServer.AfterDeleteForceCoherency(Table: TSQLRecordClass;
  aID: integer): boolean;
var T, Where: integer;
    RecRef: TRecordReference;
begin
  result := true; // success if no property found
  Where := 0; // make compiler happy
  RecRef := RecordReference(Model,Table,aID);
  if RecRef<>0 then
  for T := 0 to high(Model.RecordReferences) do
  with Model.RecordReferences[T] do begin
    case FieldType of
    sftRecord: // TRecordReference published field
      Where := RecRef;
    sftID:     // TSQLRecord published field
      if FieldRecordClass=Table then
        Where := aID else
        continue;
    else continue;
    end;
    // set Field=0 where Field references aID
//    UpdateField(Model.Tables[TableIndex],Where,FieldName^,0,False);  
      Delete(Model.Tables[TableIndex],Where);
  end;
end;

#165 Re: mORMot 1 » How to use ManyDelete and BatchDelete together » 2011-09-21 07:42:54

There is a "procedure/function" that erases all the relationships are no longer valid?
How to delete a record in one table and automatically to delete  all the relationships of same record?

Thanks corchi

#166 Re: mORMot 1 » How to use ManyDelete and BatchDelete together » 2011-09-16 11:56:56

I imagined it, but i have one table and more relations and anywhere i delete the record i must to remeber to delete all relations connected to the record.

You know a better way to delete a record and all relationships without having to cycle all the records one by one?

thanks

#167 Re: mORMot 1 » How to use ManyDelete and BatchDelete together » 2011-09-16 07:03:40

please help? how to use manydelete in a batch

#168 mORMot 1 » How to use ManyDelete and BatchDelete together » 2011-09-12 08:55:18

corchi72
Replies: 6

I wanted to replace

1)ADatabase.Delete (TSQLField, FIDS [i]); 

with

2)ADatabase.BatchDelete (FIDS [i]);

but I have not figured out how do I delete table relationships TSQLField with TSQLQvw?  (AQvw.Fields)

I have to do a cycle and delete one  at a time?

if ADatabase.TransactionBegin(TSQLField) then
begin
 ADatabase.BatchStart(TSQLField);
          for I := 0 to Length(fIds) - 1 do
          begin
              if not (Progress.fCancel) then
              begin
       
//              ADatabase.Delete(TSQLField,fIds[i]);
              ADatabase.BatchDelete(fIds[i]);
              AQvw.Fields.ManyDelete(ADatabase, AQvw.ID, fIds[i]);
              Progress.Position := i;

              end
              else
               begin
                 
                 ADatabase.BatchAbort;
                 ADatabase.RollBack;
                 exit;
               end;
          end;

          ADatabase.BatchSend(Results);
          ADatabase.Commit;
end;

Thanks corchi

#169 Re: mORMot 1 » CreateAndFillPrepare(ClientDB, fIds); how to add new record » 2011-07-29 13:58:37

You're right for the example above is fast,
but  the below example becomes slower .
In the following example, I have to filter "TSQLFile" for users, roles, and groups.
It is very heavy to run every time that i add a new record.

class function TSQLQvw.LoadQvwsForUser(ClientDB: TSQLRestClientUri;const AUser: TSQLUser;Onlypublished:Boolean=false ):TSQLQvw;
var
 fIds,fIds2,fIds3,fIds4,fIds5: TIntegerDynArray;
 ARole: TSQLRole;
 AGruppo :TSQLGruppo;
 i:Integer;
 fIdsIndexCount: integer;
 function checkPublished(ID:Integer):boolean;
 var
   AQvw:TSQLQvw;
 begin
   result := false;
   try
     AQvw := TSQLQvw.Create;
     if ClientDB.Retrieve(ID,AQvw) then
        result := AQvw.Owner<>AUser.Name;
   finally
     AQvw.Free;
   end;
 end;
begin
  result := nil;
  fIdsIndexCount := 0;
  AUser.File.DestGet(ClientDB, AUser.ID, fIds);
//  for I := 0 to Length(fIds) - 1 do
//      AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);

  CopyAndSortInteger(Pointer(fIds),Length(fIds),fIds4);

  AUser.Groups.FillMany(ClientDB, AUser.ID);
  while AUser.Groups.FillOne do
    begin
      if AUser.Groups.Dest <> nil then
        try
          AGruppo:= TSQLGruppo.Create(ClientDB, integer(AUser.Groups.Dest));

          AGruppo.File.DestGet(ClientDB, AGruppo.ID, fIds);
          fIdsIndexCount := Length(fIds4);
          for I := 0 to Length(fIds) - 1 do
              AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);

          AGruppo.Roles.FillMany(ClientDB, AGruppo.ID);
          while AGruppo.Roles.FillOne do
          begin
            if AGruppo.Roles.Dest <> nil then
            try
              ARole:= TSQLRole.Create(ClientDB, integer(AGruppo.Roles.Dest));

              ARole.File.DestGet(ClientDB, ARole.ID, fIds);
              fIdsIndexCount := Length(fIds4);
              for I := 0 to Length(fIds) - 1 do
                  AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);
            finally
              FreeAndNil(ARole);
            end;
          end;

        finally
          FreeAndNil(AGruppo);
        end;

    end;

  AUser.Roles.FillMany(ClientDB, AUser.ID);

  while AUser.Roles.FillOne do
    begin
      if AUser.Roles.Dest <> nil then
        try
          ARole:= TSQLRole.Create(ClientDB, integer(AUser.Roles.Dest));

          ARole.File.DestGet(ClientDB, ARole.ID, fIds);
          fIdsIndexCount := Length(fIds4);
          for I := 0 to Length(fIds) - 1 do
              AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);

        finally
          FreeAndNil(ARole);
        end;
    end;


 if Onlypublished then
  begin
     for I := Length(fIds4)-1  downto 0 do
     begin
        if not checkPublished(fIds4[i]) then
        begin
           DeleteInteger(fIds4,i);
        end;

     end;

  end;

    if Length(fIds4)>0 then
    begin
      result := TSQLQvw.CreateAndFillPrepare(ClientDB, fIds4);
    end
    else
      result := TSQLQvw.CreateAndFillPrepare(ClientDB,'Owner = '''+ AUser.Name+'''')

end;

#170 Re: mORMot 1 » CreateAndFillPrepare(ClientDB, fIds); how to add new record » 2011-07-29 12:22:56

You're right for the example above is fast,
but  the below example becomes slower .
In the following example, I have to filter "TSQLFile" for users, roles, and groups.
It is very heavy to run every time that i add a new record.

class function TSQLQvw.LoadQvwsForUser(ClientDB: TSQLRestClientUri;const AUser: TSQLUser;Onlypublished:Boolean=false ):TSQLQvw;
var
 fIds,fIds2,fIds3,fIds4,fIds5: TIntegerDynArray;
 ARole: TSQLRole;
 AGruppo :TSQLGruppo;
 i:Integer;
 fIdsIndexCount: integer;
 function checkPublished(ID:Integer):boolean;
 var
   AQvw:TSQLQvw;
 begin
   result := false;
   try
     AQvw := TSQLQvw.Create;
     if ClientDB.Retrieve(ID,AQvw) then
        result := AQvw.Owner<>AUser.Name;
   finally
     AQvw.Free;
   end;
 end;
begin
  result := nil;
  fIdsIndexCount := 0;
  AUser.File.DestGet(ClientDB, AUser.ID, fIds);
//  for I := 0 to Length(fIds) - 1 do
//      AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);

  CopyAndSortInteger(Pointer(fIds),Length(fIds),fIds4);

  AUser.Groups.FillMany(ClientDB, AUser.ID);
  while AUser.Groups.FillOne do
    begin
      if AUser.Groups.Dest <> nil then
        try
          AGruppo:= TSQLGruppo.Create(ClientDB, integer(AUser.Groups.Dest));

          AGruppo.File.DestGet(ClientDB, AGruppo.ID, fIds);
          fIdsIndexCount := Length(fIds4);
          for I := 0 to Length(fIds) - 1 do
              AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);

          AGruppo.Roles.FillMany(ClientDB, AGruppo.ID);
          while AGruppo.Roles.FillOne do
          begin
            if AGruppo.Roles.Dest <> nil then
            try
              ARole:= TSQLRole.Create(ClientDB, integer(AGruppo.Roles.Dest));

              ARole.File.DestGet(ClientDB, ARole.ID, fIds);
              fIdsIndexCount := Length(fIds4);
              for I := 0 to Length(fIds) - 1 do
                  AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);
            finally
              FreeAndNil(ARole);
            end;
          end;

        finally
          FreeAndNil(AGruppo);
        end;

    end;

  AUser.Roles.FillMany(ClientDB, AUser.ID);

  while AUser.Roles.FillOne do
    begin
      if AUser.Roles.Dest <> nil then
        try
          ARole:= TSQLRole.Create(ClientDB, integer(AUser.Roles.Dest));

          ARole.File.DestGet(ClientDB, ARole.ID, fIds);
          fIdsIndexCount := Length(fIds4);
          for I := 0 to Length(fIds) - 1 do
              AddSortedInteger(fIds4,fIdsIndexCount,fIds[i]);

        finally
          FreeAndNil(ARole);
        end;
    end;


 if Onlypublished then
  begin
     for I := Length(fIds4)-1  downto 0 do
     begin
        if not checkPublished(fIds4[i]) then
        begin
           DeleteInteger(fIds4,i);
        end;

     end;

  end;

    if Length(fIds4)>0 then
    begin
      result := TSQLQvw.CreateAndFillPrepare(ClientDB, fIds4);
    end
    else
      result := TSQLQvw.CreateAndFillPrepare(ClientDB,'Owner = '''+ AUser.Name+'''')

end;

#171 Re: mORMot 1 » CreateAndFillPrepare(ClientDB, fIds); how to add new record » 2011-07-29 11:03:44

My code is:

{ TSQLFile }
class function TSQLFile.LoadFilesForQvw(ClientDB: TSQLRestClientUri;const AQvw: TSQLQvw):TSQLFile;
var
 fIds: TIntegerDynArray;
begin
  result := nil;
  AQvw.Files.DestGet(ClientDB, AQvw.ID, fIds);
  if Length(fIds)>0 then
  begin
    result := TSQLFile.CreateAndFillPrepare(ClientDB, fIds);
  end
  else
    result := TSQLFile.CreateAndFillPrepare(ClientDB,'Owner = '''+ AQvw.Name+'''');
end;
......

procedure TFrmToolBarMain.ActFiltersExecute(Sender: TObject);
var
 AFile: TSQLFile;
begin
  Try
      FileDlg := TFileDlg.Create(self) ;
      AFile:= TSQLFile.LoadFilesForQvw( currentClient ,currentQvw);
      if Assigned(AFile) then
      begin
        FileDlg.SetTable(currentClient,currentQvw,currentUser,AFile);
        FileDlg.ShowModal;
      end;
  finally
      FreeAndNil(FileDlg);
  end;

end;


....


procedure TFileDlg.ActAddExecute(Sender: TObject);
var
  aRec: TSQLFile;
  newID:Integer;
  refreshed:Boolean;
  FileDS : TFileDatasource;
begin
  inherited;

    aRec:= TSQLFile.Create;
  try
    aRec.Owner      := AQvw.Name;
    aRec.Created    := Iso8601Now;
    aRec.Modified   := aRec.Created;
    newID:= ADatabase.Add(aRec,true);

    aRec.Name       := format('File%d', [newID]);
    AQvw.Files.ManyAdd(ADatabase,AQvw.ID,newID,true);
    Edit(aRec,'Add',false);
  finally
    FreeAndNil(aRec);
  end;

//Here I am forced to run "TSQLFile.CreateAndFillPrepare (ClientDB, FIDS)," otherwise I do not see the new "ID" (inserted record)

  try
     tb.BeginUpdate;
     fRec:=  TSQLFile.LoadFilesForQvw( currentClient ,currentQvw);
     FileDS := TFileDatasource.Create(tb, ADatabase,fRec);
     tb.DataController.CustomDataSource := FileDS;

    finally
     tb.EndUpdate;
  end;

end;

#172 mORMot 1 » CreateAndFillPrepare(ClientDB, fIds); how to add new record » 2011-07-29 10:20:14

corchi72
Replies: 7

Hello time ago I asked you about  fillprepare and FillRow, see link http://synopse.info/forum/viewtopic.php?id=188.
I eventually used "TSQLFile.CreateAndFillPrepare (ClientDB, FIDS)," to create a "resultset", I used "Client.Update (Rec)" and "Client.UpdateFromServer ([Table], Refreshed);" to update a records on the server and display the result in a quantumgrid and up to here everything is working.
Now I have the problem that if I add a record to the table "TSQLFile" I'm forced to run again "TSQLFile.CreateAndFillPrepare (ClientDB, FIDS);" to view data in the grid, then I ask you can I not run a ResultSet.Add and then ResultSet.Refresh.
I ask this because FLDS is a "FIDS: TIntegerDynArray," is the result of a non-functioning, which is cumbersome if you have to run every Add, Remove the recordset

Thanks, sorry for my english.

#173 mORMot 1 » how to test the server connection before execute the client http » 2011-07-19 08:08:14

corchi72
Replies: 1

Hi,
  if i execute the connection with the server that is not started, i have a exception.

procedure LoadClientDatabase(var ClientDB: TSQLRestClientDB; ServerName: string; Port: Integer);
begin
  try
    Model := GetDatabaseModel('root');
    ClientDB := TSQLRestClientDB(TSQLite3HttpClient.Create(ServerName, IntToStr(Port), Model));
  except
    //on E: Exception do
    // handle initialization error here
  end;
end;

Can I avoid the exception and perform a test to see if the server is reachable or started?

thanks corchi

#174 Re: mORMot 1 » I can run a server function from a client station? » 2011-06-30 07:40:16

ok thanks,
I have read and produced the following example that sends a filename to the server which returns the string read xml file in the directory server:

unit FileTables
....
function TServiceServer.DataAsXML(aRecord: TSQLRecord;
  aParameters: PUTF8Char; const aSentData: RawUTF8; out aResp, aHead: RawUTF8): Integer;
var //aData: TSQLRawBlob;
   sfilename:RawUTF8;
   XmlDoc: TNativeXml;
   aData: RawUTF8 ;

begin
  writeln('Start DataAsXML');
  if not UrlDecodeNeedParameters(aParameters,'FILENAME') then begin
    result := 404; // invalid Request
    writeln('invalid Request');
    exit;
  end;
  while aParameters<>nil do begin
    UrlDecodeValue (aParameters,'FILENAME=',sfilename,@aParameters);
  end;
  writeln(format('filename: %s',[sfilename]));

  if FileExists(sfilename) then
  begin
      writeln(format('Exist file: %s',[sfilename]));
     try
        XmlDoc := TNativeXml.Create(nil);
        XmlDoc.LoadFromFile(sfilename);
        if (XmlDoc <> nil) Then
        begin
           aData := XmlDoc.WriteToLocalString;
        end;
     finally
        XmlDoc.Free;
     end;
  end
  else
   begin
    result := 404; // invalid Request
    exit; // we need a valid record and its ID
   end;

  aResp := JSONEncodeResult([aData]);
  //aResp := JSONEncodeResult([SynCommons.BinToHex(aData)]);
  // idem: aResp := JSONEncode(['result',BinToHex(aRecord.fData)],TempMemoryStream);
  result := 200; // success
end;
..............................end FileTables

........ Client procedure
Var

  sfilename:String;
  XmlDoc: TNativeXml;
  aData: RawUTF8;
begin 
..
aData := ADatabaseServer.CallBackGetResult('DataAsXML',['filename',StringtoUTF8(sfilename)]);
                 if Length(aData)>0 then
                 begin
                   sfilename := nome;
                   sfilename := format('%s%s.xml',[GetTempDir, ReplaceStr(sfilename,'\','_')]) ;

                   XmlDoc.ReadFromString(UTF8ToString(aData));
                   XmlDoc.SaveToFile(sfilename);
                 end;
...
end;

but now I want to send the xml string to the server and the server would that save the document with a specific name

I wrote the following example using "CallBackPut" but I can not send the parameters type "filename" to "XMLAsData",
and I can not read the parameters returned by procedure "aResp: JSONEncodeResult = ([sFileName]);"



unit FileTables
....
function TServiceServer.XMLAsData(aRecord: TSQLRecord;
  aParameters: PUTF8Char; const aSentData: RawUTF8; out aResp, aHead: RawUTF8): Integer;
var //aData: TSQLRawBlob;
   sfilename:RawUTF8;
   XmlDoc: TNativeXml;
   aData: RawUTF8 ;
   Node: TXmlNode;
begin
  writeln('Start XMLAsData');
//  if not UrlDecodeNeedParameters(aParameters,'FILENAME') then begin
//    result := 404; // invalid Request
//    writeln('invalid Request');
//    exit;
//  end;
//  while aParameters<>nil do begin
//    UrlDecodeValue (aParameters,'FILENAME=',sfilename,@aParameters);
//  end;
//  writeln(format('filename: %s',[sfilename]));

  if length(aSentData)>0 then
  begin
//      writeln(format('Exist data: %s',[aSentData]));
     try
        XmlDoc := TNativeXml.Create(nil);
        XmlDoc.ReadFromString(UTF8ToString(aSentData));
         sfilename := format('%s%s.xml',[GetTempDir, ReplaceStr(sfilename,'\','_')]) ;
        XmlDoc.SaveToFile(sfilename);
     finally
        XmlDoc.Free;
     end;
  end
  else
   begin
    result := 404; // invalid Request
    exit; // we need a valid record and its ID
   end;

  aResp := JSONEncodeResult([sfilename]);
  writeln(format('Exist data: %s',[aResp]));
  // idem: aResp := JSONEncode(['result',BinToHex(aRecord.fData)],TempMemoryStream);
  result := 200; // success
end;

..............................end FileTables


........ Client procedure
Var

  sfilename:String;
  XmlDoc: TNativeXml;
  aData: RawUTF8;
  aResponse: RawUTF8;
begin 
...
aData :=  " Here insert the xml string !!!!!!!!"
ADatabaseServer.CallBackPut('XMLAsData',aData,aResponse);
sfilename := UTF8ToString(aResponse); "the value returned is always empty !!!!!!!!"


..
end;

can you help me ?

thanks corchi

#175 Re: mORMot 1 » I can run a server function from a client station? » 2011-06-28 12:57:35

I only found this documentation,
http://synopse.info/forum/viewtopic.php?id=256

where I can entice the right one?

thanks corchi

#176 mORMot 1 » I can run a server function from a client station? » 2011-06-28 12:10:00

corchi72
Replies: 4

I can run a server function from a client station if I used TSQLRestServerDB TSQLite3HttpClient server side and client-side

I need to send me an xml file from the server (I read files from a directory server)

thanks corchi

#178 mORMot 1 » Error To compile SQLite3UIEdit version 1.14 » 2011-06-15 07:50:57

corchi72
Replies: 14

Today I downloaded the "6f2a76894f" Synops of, but completing an error occurs in file "SQLite3UIEdit"at line

aCaption: = CaptionName (OnCaptionName, @ P ^. Name);

I saw that you have modified the file "SQLite3i18n" and you have replaced

text: = TranslateOne (CompName, ppi ^. Name);

with

text: = TranslateOne (CompName, ppi ^. ShortName);

Thank corchi

#179 Re: mORMot 1 » an error occurs if I use class SQLite3, ecc in my component » 2011-04-21 12:37:13

I do not understand, AFAIK is a directive compiler?
I found only these two lines of comments that refer to AFAIK

1) // - it's still fast, faster than any DB AFAIK, around 500 updates
...
2){ Below we just ignore the value of next string token.
       
          We can do this -- because PasDoc (at least for now)
          does not recursively parse units on "uses" clause.
          So we are not interested in the value of
          given string (which should be a file-name (usually relative,
          but absolute is also allowed AFAIK) with given unit.)

#180 Re: mORMot 1 » an error occurs if I use class SQLite3, ecc in my component » 2011-04-21 07:42:39

odd because I created a variable called "$ (Synops) " with the path of the source of "Synops OpenSource" and in fact if I create a simple project it works.
The component is very simple and is what I set out below.

$(Synopse) = c:\.....\Synopse OpenSource


$(sqlite3obj); where i put sqlite3.obj and sqlite3fts3.obj
$(Synopse);
$(Synopse)\SQLite3;

package SQliteComponent;

{$R *.res}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$IMPLICITBUILD ON}
{$DEFINE USETMSPACK}

requires
  rtl;

contains
  SQLite3UI in '..\Synopse OpenSource\SQLite3\SQLite3UI.pas';

end.

//is a simple package that uses your unit

unit SQLite3UI;
....
procedure Register;
begin
  RegisterComponents('Synopse',[TSynLabeledEdit]);
end;

Error: impossible to find file "C:\......\SQLite3i18n.pas"
Why

#181 mORMot 1 » an error occurs if I use class SQLite3, ecc in my component » 2011-04-20 13:17:05

corchi72
Replies: 5

I created a unit called "FileTables" that uses classes and SQLite3 SynCommons but when compiling I get errors "can not find the file SQLite3.pas"even though I entered the path in the Delphi library.

Using the same unit from a project the error does not occur.
What should I add to the component you do not need to add to a project?

unit FileTables;

interface

uses
  Windows,
  SysUtils,
  SynCommons,
  SQLite3,
  SQLite3Commons,
  SQLite3HttpClient,SQLite3HttpServer;

...

#182 Re: mORMot 1 » how to invoke a TLabeledEdit created automatically by TRecordEditForm » 2011-04-15 08:41:22

Ok I put this new procedure in the base form, and when I writing into a textbox I will write : SetValue('Fieldname','value');


procedure TFrmEditBase.SetValue(FieldName:String; Value: String);
var
 FieldIndex:Integer;
 C: TWinControl;
 CLE: TLabeledEdit absolute C;
 U: RawUTF8;
 P: PPropInfo;
 Props: TSQLRecordProperties;
begin
    Props := fRec.RecordProps;
    FieldIndex := Props.FieldIndexFromRawUTF8(FieldName);
    if cardinal(Props.FieldIndexFromRawUTF8(FieldName))<cardinal(length(fFieldComponents)) then
    begin
       C := fFieldComponents[FieldIndex];
       C.SetFocus;
       if C.InheritsFrom(TLabeledEdit) then begin
       begin
       CLE.Text :=  Value;

       U := S2U(CLE.Text);
       P := Props.Fields[FieldIndex];
       P^.SetValue(fRec,pointer(U)); // do conversion for every string type

       end;
    end

    end;
end;

Thanks

#183 mORMot 1 » how to invoke a TLabeledEdit created automatically by TRecordEditForm » 2011-04-13 14:26:43

corchi72
Replies: 3

Hello,
I have created a form inheriting class (TRTTIForm), copiando quanto c'è scritto nella unit  SQLite3UIEdit,  I have attached the code below:

unit UFrmEditBase;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, ActnList, StdCtrls, ExtCtrls, AdvPanel,

  SQLite3UIEdit,
  SynCommons, SynCrypto, SynGdiPlus,
  SQLite3Commons,
  SQLite3UILogin,
  SQLite3UI,
  SQLite3i18n,SQLite3ToolBar, AdvGlowButton
  ;

type
  TFrmEditBase = class(TRTTIForm)
    ActionList1: TActionList;
    ActAdd: TAction;
    ActRemove: TAction;
    ActSave: TAction;
    ActCancel: TAction;
    ActClose: TAction;
    PopupMenu1: TPopupMenu;
    Nuovo1: TMenuItem;
    Annulla1: TMenuItem;
    Chiudi1: TMenuItem;
    Chiudi2: TMenuItem;
    Salva1: TMenuItem;
    N1: TMenuItem;
    N2: TMenuItem;
    Scroll: TScrollBox;
    BottomPanel: TPanel;
    BtnSave: TAdvGlowButton;
    BtnCancel: TAdvGlowButton;
    procedure FormShow(Sender: TObject);
    procedure ActSaveExecute(Sender: TObject);
    procedure ActCancelExecute(Sender: TObject);
  private
    procedure Save(Sender: TObject);


  protected
    fRec: TSQLRecord;
    fClient: TSQLRestClient;
    ADatabase: TSQLRestClient;
    fOnComponentValidate: TOnComponentValidate;
    /// as created by SetRecord()
    fFieldComponents: array of TWinControl;
    fFieldCaption: array of string;
    // avoid Windows Vista and Seven screen refresh bug (at least with Delphi 7)
    fReadOnly: boolean;
    procedure WMUser(var Msg: TMessage); message WM_USER;
  public
    /// create the corresponding components on the dialog for editing a Record
    // - to be used by OnComponentCreate(nil,nil,EditForm) in order
    // to populate the object tree of this Form
    // - create field on the window for all published properties of the
    // supplied TSQLRecord instance
    // - properties which name starts by '_' are not added to the UI window
    // - user can customize the component creation by setting the
    // OnComponentCreate / OnComponentCreated events
    // - the supplied aRecord instance must be available during all the
    // dialog window modal apparition on screen
    // - by default, all published fields are displayed, but you can specify
    // a CSV list in the optional CSVFieldNames parameter
    // - editor parameters are taken from the optional Ribbon parameter,
    // and its EditFieldHints/EditExpandFieldHints/EditFieldNameWidth properties
    // - if Ribbon is nil, FieldHints may contain the hints to be displayed on
    // screen (useful if your record is not stored in any TSQLRestClient, but
    // only exists in memory); you can set FieldNamesWidth by hand in this case
    procedure SetRecord(aClient: TSQLRestClient; aRecord: TSQLRecord;
      CSVFieldNames: PUTF8Char=nil; Ribbon: TSQLRibbon=nil;
      FieldHints: string=''; FieldNamesWidth: integer=0; aCaption: string='');
    /// the associated Record to be edited
    property Rec: TSQLRecord read fRec;
    /// the associated database Client, used to access remote data
    property Client: TSQLRestClient read fClient;
    /// event called to check if the content of a field on form is correct
    // - is checked when the user press the "Save" Button
    // - if returns false, component is focused and window is not closed
    property OnComponentValidate: TOnComponentValidate read fOnComponentValidate write fOnComponentValidate;
    property ReadOnly: boolean read fReadOnly write fReadOnly;
  end;


var
  FrmEditBase: TFrmEditBase;


function Cypher(const Title: string; var Content: TSQLRawBlob; Encrypt: boolean): boolean;

implementation

{$R *.dfm}



resourcestring
  sEdit = 'Edit';
  sVerb = '%s %s';
  sInvalidFieldN = 'Invalid "%s" Field';


procedure TFrmEditBase.SetRecord(aClient: TSQLRestClient;
  aRecord: TSQLRecord; CSVFieldNames: PUTF8Char=nil; Ribbon: TSQLRibbon=nil;
  FieldHints: string=''; FieldNamesWidth: integer=0; aCaption: string='');
var i,j, aID, Y, aHeight, aWidth, CW: integer;
    RibbonParams: PSQLRibbonTabParameters;
    ExpandFieldHints: boolean;
    E: PEnumType;
    EP: PShortString;
    Group: TGroupBox;
    C: TWinControl;
    CLE: TLabeledEdit absolute C;
    CNE: TSynLabeledEdit absolute C;
    CC: TCheckbox absolute C;
    CB: TCombobox absolute C;
    aClassType: TSQLRecordClass;
    Sets: cardinal;
    IDClass: TSQLRecordClass;
    aHint: string;
    aName: RawUTF8;
    FieldNameToHideCSV: PUTF8Char;
    P: PPropInfo;
    PHint: PChar; // map FieldHints
begin
  if (self=nil) or (aRecord=nil) then
    exit; // avoid GPF
  RibbonParams := Ribbon.GetParameter(aRecord.RecordClass);
  if RibbonParams=nil  then begin
    ExpandFieldHints := (FieldHints<>'');
    FieldNameToHideCSV := nil;
    if FieldNamesWidth=0 then
      FieldNamesWidth := 200; // default value
  end else
  with RibbonParams^ do begin
    FieldNamesWidth := EditFieldNameWidth;
    if FieldNamesWidth=0 then
      FieldNamesWidth := 200; // default value
    if EditFieldHints<>nil then
      FieldHints := LoadResString(EditFieldHints);
    ExpandFieldHints := EditExpandFieldHints;
    FieldNameToHideCSV := pointer(EditFieldNameToHideCSV);
  end;
  fRec := aRecord;
  fClient := aClient;
  CW := Scroll.ClientWidth;
  aName := aClient.MainFieldValue(aRecord.RecordClass,aRecord.ID,true);
  if aCaption='' then begin
    if Caption='' then
      aCaption := sEdit else
      aCaption := Caption;
    aCaption := format(sVerb,[aCaption,aRecord.CaptionName]);
    if aName<>'' then
      aCaption := aCaption+' - '+U2S(aName); // add current record name
  end;
  Caption := '  '+aCaption;
  with TStaticText.Create(Scroll) do begin
    Parent := Scroll;
    Alignment := taCenter;
    Font.Style := [fsBold];
    Font.Size := 12;
    Font.Color := clTeal;
    Caption := aCaption;
    SetBounds(8,16,CW-48,Height);
    Y := Top+Height+16;
  end;
  with TBevel.Create(Scroll) do begin
    Parent := Scroll;
    SetBounds(8,Y-12,CW-32,4);
    Shape := bsTopLine;
  end;
  aClassType := PPointer(aRecord)^;
  dec(CW,FieldNamesWidth+32);
  PHint := pointer(FieldHints);
  with aClassType.RecordProps do begin
    SetLength(fFieldComponents,length(Fields));
    SetLength(fFieldCaption,length(Fields));
    for i := 0 to High(Fields) do begin
      aHint := GetNextItemString(PHint,'|'); // ALL fields are listed: do it now
      P := Fields[i];
      aName := FieldsName[i];
      if ((FieldType[i] in [ // must match   case "FieldType[i] of"  below
          sftRecord, sftTimeLog, sftCurrency, sftDateTime, sftFloat, sftBlob]) and
           not Assigned(OnComponentCreate)) or
         ((FieldNameToHideCSV<>nil) and
          (FindCSVIndex(FieldNameToHideCSV,aName,',',false)>=0)) or
         ((CSVFieldNames<>nil) and
          (FindCSVIndex(CSVFieldNames,aName,',',false)<0)) then
        continue; // display properties listed in optional CSVFieldNames parameter
      aCaption := CaptionName(OnCaptionName,@P^.Name);
      fFieldCaption[i] := aCaption;
      if (aHint<>'') and ExpandFieldHints then
        with TLabel.Create(Scroll) do begin // show hint above field
          Parent := Scroll;
          Font.Color := clNavy;
          Font.Size := 8;
          AutoSize := True;
          WordWrap := true;
          SetBounds(FieldNamesWidth,Y+8,CW-32,24);
          Caption:= aHint;
          inc(Y,Height+10);
          aHint := ''; // mark hint displayed on window -> no popup needed
        end;
      aHeight := 24;
      // try custom component creation
      if not Assigned(OnComponentCreate) then
        C := nil else
        C := OnComponentCreate(aRecord,P,Scroll);
      if C=nil then begin
        // default creation from RTTI, if not handled by OnComponentCreate()
        case FieldType[i] of
          sftRecord, sftTimeLog, sftCurrency, sftDateTime, sftFloat, sftBlob:
            ; // not implemented yet (not needed yet, to be honest)
          sftInteger:
            // integer field is handled by a TSynLabeledEdit component
            if P^.PropType^^.Kind=tkInteger then begin // tkInt64 not handled yet
              CNE := TSynLabeledEdit.Create(Scroll);
              CNE.Value := P^.GetOrdValue(aRecord);
              CNE.RaiseExceptionOnError := true; // force show errors on screen
            end;
          sftEnumerate: begin
            // enumeration is handled by a TComboBox with all possible values
            E := P^.PropType^^.EnumBaseType;
            CB := TComboBox.Create(Scroll);
            CB.Parent := Scroll; // need parent now for CB.Items access
            CB.Style := csDropDownList;
            EP := @E^.NameList;
            for j := 0 to E^.MaxValue do begin
              CB.Items.Add(CaptionName(OnCaptionName,EP));
              inc(PtrInt(EP),ord(EP^[0])+1); // next enumeration item
            end;
            CB.ItemIndex := P^.GetOrdValue(aRecord);
          end;
          sftID:
          if aClient<>nil then begin
            // ID field (TSQLRecord descendant) is handled by a TComboBox component
            // with all possible values of the corresponding TSQLRecord descendant
            IDClass := TSQLRecordClass(P^.PropType^^.ClassType^.ClassType);
            CB := TComboBox.Create(Scroll);
            CB.Parent := Scroll; // need parent now for CB.Items access
            CB.Style := csDropDownList;
            aID := P^.GetOrdValue(aRecord);
            with IDClass.RecordProps do
            if MainField[true]>=0 then begin
              aClient.OneFieldValues(IDClass,FieldsName[MainField[true]],'',CB.Items,@aID);
              CB.ItemIndex := aID; // @aID now contains the found index of aID
            end;
          end;
          sftSet: begin
            // enumeration set if handled by a TGroupBox component contaning one
            // TCheckBox for each enumeration value
            Group := TGroupBox.Create(Scroll); // add left-sided label
            Group.Parent := Scroll;
            Group.Font.Style := [fsBold];
            Group.Caption := ' '+aCaption+' ';
            Group.Tag := i+1; // for BtnSaveClick() event
            if Assigned(OnComponentCreated) then // allow component customization
              OnComponentCreated(aRecord,P,Group); // e.g. set Group.Enabled := false
            Sets := P^.GetOrdValue(aRecord);
            E := P^.PropType^^.SetEnumType;
            aWidth := 200;
            EP := @E^.NameList;
            for j := 0 to E^.MaxValue do begin
              if EP^[0]>#25 then begin
                aWidth := 250; // wider group box for large enumeration caption
                break;
              end;
              inc(PtrInt(EP),ord(EP^[0])+1); // next enumeration item
            end;
            Group.SetBounds(FieldNamesWidth,Y+4,aWidth,40+20*E.MaxValue);
            dec(aWidth,20);
            EP := @E^.NameList;
            for j := 0 to E^.MaxValue do
              with TCheckBox.Create(Scroll) do begin // add set checkboxes
                Parent := Group;
                Font.Style := [];
                Caption := CaptionName(OnCaptionName,EP);
                inc(PtrInt(EP),ord(EP^[0])+1); // next enumeration item
                SetBounds(16,16+20*j,aWidth,20);
                if aHint<>'' then begin
                  Hint := aHint;
                  ShowHint := True;
                end;
                Checked := GetBit(Sets,j);
                Enabled := Group.Enabled;
                Tag := i+1+(j+1) shl 8;  // for BtnSaveClick() event
              end;
            inc(Y,Group.Height+12);
            continue;
          end;
          sftBoolean: begin
            // boolean is handled by a TCheckBox component
            CC := TCheckBox.Create(Scroll);
            CC.Parent := Scroll; // initialize font
            CC.Font.Style := [fsBold];
            CC.Checked := boolean(P^.GetOrdValue(aRecord));
            CC.Caption := aCaption;
          end;
          sftUTF8Text, sftAnsiText: begin
            // text field is handled by a  TLabeledEdit component
            CLE := TLabeledEdit.Create(Scroll);
            {$ifdef UNICODE}
            if P^.PropType^^.Kind=tkUString then
              CLE.Text := P^.GetUnicodeStrValue(aRecord) else
            {$endif}
              CLE.Text := U2S(P^.GetValue(aRecord,False)); // convert in GetValue()
            CLE.Name := P^.Name;
          end;
        end;
      end;
      if (C<>nil) and (C<>self) and (C<>Scroll) then begin
        // we reached here if a component was added on screen for this field
        C.Parent := Scroll;
        C.Tag := i+1;  // for BtnSaveClick() event
        if aHint<>'' then begin
          C.Hint := aHint; // show hint text as popup
          C.ShowHint := true;
        end;
        if Assigned(OnComponentCreated) then // allow component customization
          OnComponentCreated(aRecord,P,C); // e.g. set C.Enabled := false
        if not C.InheritsFrom(TCheckBox) then
        if C.InheritsFrom(TLabeledEdit) then begin
          CLE.EditLabel.Font.Style := [fsBold];
          CLE.EditLabel.Caption := aCaption;
          CLE.LabelPosition := lpLeft;
        end else
        with TLabel.Create(Scroll) do begin // add label left-sided to the field
          Parent := Scroll;
          Font.Style := [fsBold];
          Caption := aCaption;
          SetBounds(8,Y+4,FieldNamesWidth-12,Height);
          Alignment := taRightJustify;
          if not C.Enabled then
            Enabled := false;
        end;
        if C.InheritsFrom(TCheckBox) then // trick to avoid black around box
          CC.SetBounds(FieldNamesWidth,Y,CW,CC.Height) else
          C.SetBounds(FieldNamesWidth,Y,200,22);
        fFieldComponents[i] := C;
        inc(Y,aHeight);
      end;
    end;
  end;
  // draw a line at the bottom of the scroll box
  with TBevel.Create(Scroll) do begin
    Parent := Scroll;
    SetBounds(8,Y+8,CW+FieldNamesWidth,16);
    Shape := bsTopLine;
  end;
  Inc(Y,BottomPanel.Height+32);
  // resize height to fit the fields (avoid bottom gap)
  if ClientHeight>Y then
    ClientHeight := Y;
end;

procedure TFrmEditBase.ActCancelExecute(Sender: TObject);
begin
  modalresult := mrCancel;
end;

procedure TFrmEditBase.ActSaveExecute(Sender: TObject);
begin
  Save(Sender);
end;

procedure TFrmEditBase.FormShow(Sender: TObject);
begin
  Application.ProcessMessages;
  Screen.Cursor := crHourGlass;
  try
    if Assigned(OnComponentCreate) then
      OnComponentCreate(nil,nil,self); // will call AddEditors() to create nodes
    SetStyle(self);
  finally
    Screen.Cursor := crDefault;
  end;
  PostMessage(Handle,WM_USER,0,0); // avoid Vista and Seven screen refresh bug
end;

procedure TFrmEditBase.WMUser(var Msg: TMessage);
var i: integer;
begin
  for i := 0 to Scroll.ControlCount-1 do
    Scroll.Controls[i].Repaint;
end;

procedure TFrmEditBase.Save(Sender: TObject);
var j, FieldIndex, SetIndex, aID: integer;
    Value: set of 0..31;
    U: RawUTF8;
    C: TWinControl;
    CLE: TLabeledEdit absolute C;
    CNE: TSynLabeledEdit absolute C;
    CC: TCheckbox absolute C;
    CB: TCombobox absolute C;
    CG: TGroupBox absolute C;
    Props: TSQLRecordProperties;
    P: PPropInfo;
    ModifiedFields: TSQLFieldBits;
    ErrMsg: string;
begin
  if Rec=nil then
    exit;
  Props := Rec.RecordProps;
  Int64(ModifiedFields) := 0;
  for FieldIndex := 0 to high(fFieldComponents) do begin
    C := fFieldComponents[FieldIndex];
    if (C=nil) or not C.Enabled then
      continue; // disabled components didn't modify their value
    assert(FieldIndex=(C.Tag and 255)-1);
    P := Props.Fields[FieldIndex];
    if Assigned(OnComponentValidate) and not OnComponentValidate(C,P) then begin
      // invalid field content -> abort saving
      C.SetFocus;
      exit;
    end;
    if C.InheritsFrom(TSynLabeledEdit) then
    try
      P^.SetOrdValue(Rec,CNE.Value); // call CNE.GetValue for range checking
      Include(ModifiedFields,FieldIndex);
    except
      on E: ESynLabeledEdit do begin // trigerred by CNE.GetValue
        CNE.SetFocus;
        ShowMessage(CNE.EditLabel.Caption+':'#13+E.Message,true);
        exit;
      end;
    end else
    if C.InheritsFrom(TLabeledEdit) then begin
      U := S2U(CLE.Text);
      P^.SetValue(Rec,pointer(U)); // do conversion for every string type
      Include(ModifiedFields,FieldIndex);
    end else
    if C.InheritsFrom(TGroupBox) then begin
      for j := 0 to CG.ControlCount-1 do
        if CG.Controls[j].InheritsFrom(TCheckBox) then
        with TCheckBox(CG.Controls[j]) do begin
          SetIndex := (Tag shr 8)-1;
          if cardinal(SetIndex)<32 then begin
            integer(Value) := P^.GetOrdValue(Rec);
            if Checked then
              include(Value,SetIndex) else
              exclude(Value,SetIndex);
            P^.SetOrdValue(Rec,integer(Value));
            Include(ModifiedFields,FieldIndex);
        end;
      end;
    end else
    if C.InheritsFrom(TCheckBox) then begin
      if CC.Tag<255 then begin
        P^.SetOrdValue(Rec,integer(CC.Checked));
        Include(ModifiedFields,FieldIndex);
      end;
    end else
    if C.InheritsFrom(TComboBox) then begin
      SetIndex := CB.ItemIndex;
      case P^.PropType^^.SQLFieldType of
        sftEnumerate:
          if SetIndex>=0 then begin
            P^.SetOrdValue(Rec,SetIndex);
            Include(ModifiedFields,FieldIndex);
          end;
        sftID: begin
          if SetIndex<0 then
            aID := 0 else
            aID := PtrInt(CB.Items.Objects[SetIndex]);
          P^.SetOrdValue(Rec,aID);
          Include(ModifiedFields,FieldIndex);
        end;
      end;
    end;
  end;
  // perform all registered filtering
  Rec.Filter(ModifiedFields);
  // perform content validation
  FieldIndex := -1;
  ErrMsg := Rec.Validate(Client,ModifiedFields,@FieldIndex);
  if ErrMsg<>'' then begin
    // invalid field content -> show message, focus component and abort saving
    if cardinal(FieldIndex)<cardinal(length(fFieldComponents)) then begin
      C := fFieldComponents[FieldIndex];
      C.SetFocus;
      Application.ProcessMessages;
      ShowMessage(ErrMsg,format(sInvalidFieldN,[fFieldCaption[FieldIndex]]),true);
    end else
      ShowMessage(ErrMsg,format(sInvalidFieldN,['?']),true);
  end else
    begin
    fClient.update(Rec);
    // close window on success
    ModalResult := mrOk;
    end;
end;


function Cypher(const Title: string; var Content: TSQLRawBlob; Encrypt: boolean): boolean;
resourcestring
  sEnterPassword = 'Enter password for this record:';
var AES: TAESFull;
    SHA: TSHA256Digest;
    PassWord: string;
    Len: integer;
begin
  result := Content='';
  if result then
    exit;
  if not TLoginForm.PassWord(Title,sEnterPassword,PassWord) then
    exit;
  SHA256Weak(S2U(PassWord), SHA);
  try
    Len := AES.EncodeDecode(SHA,256,length(Content),Encrypt,nil,nil,Pointer(Content),nil);
    if Len<0 then
      exit;
    SetString(Content,PAnsiChar(AES.outStreamCreated.Memory),Len);
    result := true;
  finally
    AES.OutStreamCreated.Free;
  end;
end;
end.

and it all works, the components are created "TLabeledEdit" etc. .. vost as in example, but when I refer to an object created at runtime what to write?
Let me explain with an example:

 TSQLUser = class(TSQLFile)
  private
    fRoles: TSQLUserRoles;
    fLogin, fPassword: RawUTF8;
    fName : RawUTF8;
    fSubName: RawUTF8;
....


function TFrmElencoUser.Edit(Rec: TSQLFile; const Title: string; ReadOnly: boolean): boolean;
var
 refreshed:Boolean;
begin
  fRec := TSQLUser(Rec);
  try
  FrmEditUser := TFrmEditUser.Create(Self);  //   TFrmEditUser = class(TFrmEditBase)
  FrmEditUser.Caption := ' '+Title;
  FrmEditUser.ReadOnly := ReadOnly;
  FrmEditUser.SetRec(ADatabase,fRec);

....
end;

function TFrmEditUser.SetRec(aClient: TSQLRestClient;const Value: TSQLUser): boolean;
begin
  result := false;
  fRec := Value;
  ADatabase := aClient;
  SetRecord(ADatabase,Value);
.....



//now I want to change the value of a property by code

procedure TFrmEditUser.changeSubName(value:String);
begin
fRec.SubName := value; //now if I run the form's save the value of the property is replaced with the same property attached to TlabelEdit.text
  
end;

so I decided to write directly into TlabelEdit.text, but I do not know how to find the one attached to the property subname.

so I added the line "CLE.Name: = P ^. Name," to name the object created at runtime

   sftUTF8Text, sftAnsiText: begin
            // text field is handled by a  TLabeledEdit component
            CLE := TLabeledEdit.Create(Scroll);
            {$ifdef UNICODE}
            if P^.PropType^^.Kind=tkUString then
              CLE.Text := P^.GetUnicodeStrValue(aRecord) else
            {$endif}
              CLE.Text := U2S(P^.GetValue(aRecord,False)); // convert in GetValue()
            CLE.Name := P^.Name; // I added this line
          end;

and I corrected the procedure "changeSubName" as follows:

procedure TFrmEditUser.changeSubName(value:String);
begin
fRec.SubName := value;
 for i := 0 to Self.ControlCount-1 do
      begin
          if self.Controls[i] is TScrollBox then
          begin
              if self.Controls[i].findcomponent('SubName') is TLabeledEdit then
                TLabeledEdit( self.Controls[i].findcomponent('SubName')).Text := fRec.SubName;
              break;
          end;
      end;

The question is: is there some other way to achieve the same result?
Thanks

#184 Re: mORMot 1 » find record by property "name" and ecc... » 2011-04-06 15:23:03

There are examples with TSQLTableJSON?

Thanks

#185 Re: mORMot 1 » find record by property "name" and ecc... » 2011-04-06 14:16:05

I'm sorry but maybe I was not clear, I have already run the above command
"TSQLField.CreateAndFillPrepar (ADatabase, FIDS), and now I just wanted to do a search on the list already exists, but if I understand it is not possible, I have to scroll all the records with "Fillone" to compare data.


var
 fIds: TIntegerDynArray;
begin
  result := nil;
  AQvw.Fields.DestGet(ADatabase, AQvw.ID, fIds);
  if Length(fIds)>0 then
  begin
    result := TSQLField.CreateAndFillPrepare(ADatabase, fIds);

I come to the point:

I am seeing a list of codes in a grid and I wanted to do a lookup table with TSQLField (daughter of TSQLQvw), also in the grid to display the description for.

#186 mORMot 1 » find record by property "name" and ecc... » 2011-04-06 10:32:08

corchi72
Replies: 4

I have created 2 classes and the relationship "one to many"  between the two classes.

  TSQLQvwFields = class(TSQLRecordMany)
  private
    fSource: TSQLQvw;
    fDest: TSQLField;
  published
    property Source:  TSQLQvw read fSource;
    property Dest: TSQLField read fDest;

  end;

  TSQLQvw = class(TSQLFile)
  private
  ..
    fFields: TSQLQvwFields;

end;

TSQLField = class(TSQLFile)
  private
    fOwner: RawUTF8;
    fEnabled: boolean;
  public

  published
    property Name;
    property Created;
    property Modified;
    property KeyWords;
    property SignatureTime;
    property Signature;

    property Owner: RawUTF8 read fOwner write fOwner;
    property Enabled: boolean read fEnabled write fEnabled;
  end;

Then I have created a function that exposes only the child records in the table SQLQvw

{ TSQLField }
function LoadFieldForQvw(ADatabase: TSQLRestClient;const AQvw: TSQLQvw):TSQLField;
var
 fIds: TIntegerDynArray;
begin
  result := nil;
  AQvw.Fields.DestGet(ADatabase, AQvw.ID, fIds);
  if Length(fIds)>0 then
  begin
    result := TSQLField.CreateAndFillPrepare(ADatabase, fIds);
  end;
end;

now I need to do a search in the range of data that I have created, what should I write?

//Example

procedure TFrmEditFileQvw.ActFieldsExecute(Sender: TObject);
var
 AField: TSQLField;
 List:TStringlist;
 i:Integer;
begin
  try
  
     List:=TStringlist.Create;
     List.Add('A001');
     List.Add('B001');

     AField:= LoadFieldForQvw( currentDatabase ,Rec);
     if Assigned(AField) then
     begin
        for i := 0 to List.Count -1 do
          if AField = List[i]  then // here  what should I write??????????
              Showmessage('I found it:...');


     end;
  finally
     FreeAndnil(List);
    
  end;

end;

Thanks

#187 Re: mORMot 1 » Error in last version :Synopse OpenSource-8455306490772f68 » 2011-03-28 12:15:58

If you fill out the code for version 8455306490772f68 gives you the error the line

   TSynToolBar = class (TAdvToolBar), because the ";" should not be there.

In addition, verifcano other errors trying to compile with the directive "USETMSPACK"

let me know if you by mistake

#188 mORMot 1 » Error in last version :Synopse OpenSource-8455306490772f68 » 2011-03-28 08:07:33

corchi72
Replies: 5

/// a TMS toolbar
  TSynToolBar = class(TAdvToolBar);
  public
...

#189 Re: mORMot 1 » how to perform a merge between two tables? » 2011-03-22 08:33:59

Certainly, I have three tables:
1) users
2) groups
3) roles

and three other reports many to many
1) user groups
2) users roles
3) groups roles

The three tables residing in a sqlite file that I put in a server.
So I created a 'client / server application.
The program is used by agents but are not always present in the company so I have to replicate the tables also in their PC with all the reports.
In addition, each agent should contain only information relating to its user, so it must have its user, only groups to which it belongs, and the roles to which it is enabled.

Managing users, groups, and roles, is made by an administrator in the sqlite file on the server, and only when each user connects to the server attempts to synchronize the 6 tables.

the 6 tables are the ones I described above, three more tables with their relations

I thank you in advance for your willingness

#190 Re: mORMot 1 » how to perform a merge between two tables? » 2011-03-21 16:59:46

excuse me explain.
I have 3 tables in the server and three tables on the client I want to keep in line without having to check if they are different because I always want to delete the three tables of the client and overwrite them with the 3 tables on the server. What should I write?

#191 Re: mORMot 1 » how to perform a merge between two tables? » 2011-03-21 14:30:51

ok Thanks

I saw that executing the function:

        FromUser.Groups.FillMany(AFromDatabase, FromUser.ID);
        while FromUser.Groups.FillOne do
        begin
            if AToDatabase.Retrieve(FromUser.Groups.Dest.ID,AGruppo) then
            begin
              if AFromDatabase.Retrieve(FromUser.Groups.Dest.ID,FromGruppo) then
              begin
                 if not AGruppo.SameValues(FromGruppo) then
                 AToDatabase.Update(FromGruppo);
              end;
            end
            else
              begin
                if AFromDatabase.Retrieve(FromUser.Groups.Dest.ID,FromGruppo) then
                 AToDatabase.Add(FromGruppo,true);
              end;
             ToUser.Groups.ManyAdd(AToDatabase,FromUser.Groups.Source.ID,FromUser.Groups.Dest.ID,true);
        end;

        FromUser.Roles.FillMany(AFromDatabase, FromUser.ID);
        while FromUser.Roles.FillOne do
        begin
            if AToDatabase.Retrieve(FromUser.Roles.Dest.ID,ARole) then
            begin
              if AFromDatabase.Retrieve(FromUser.Roles.Dest.ID,FromRole) then
              begin
                 if not ARole.SameValues(FromRole) then
                 AToDatabase.Update(FromRole);
              end;
            end
            else
              begin
                if AFromDatabase.Retrieve(FromUser.Roles.Dest.ID,FromRole) then
                 AToDatabase.Add(FromRole,true);
              end;
            ToUser.Roles.ManyAdd(AToDatabase,FromUser.Roles.Source.ID,FromUser.Roles.Dest.ID,true);
        end;

        FromUser.Groups.FillMany(AFromDatabase, FromUser.ID);
        while FromUser.Groups.FillOne do
        begin
            if AFromDatabase.Retrieve(FromUser.Groups.Dest.ID,FromGruppo) then
            begin
              if AToDatabase.Retrieve(FromUser.Groups.Dest.ID,AGruppo) then
              begin
                FromGruppo.Roles.DestGet(AFromDatabase, FromGruppo.ID, fIds);
                for i := 0 to Length(fIds) - 1 do
                begin
                    AGruppo.Roles.ManyAdd(AToDatabase, AGruppo.ID, fIds[i],True);
                end;
              end;
            end;
        end;

is not maintained in the source ID is created, but again, so I decided to cancallare always the destination table and copy all records ever in the source table, what should I write to perform INSERT and DELETE * FROM table for each record?

Can you help?

#192 mORMot 1 » how to perform a merge between two tables? » 2011-03-16 15:02:41

corchi72
Replies: 7

Hello I am developing a program to work with databases on a server and a db with the same tables on a client, I perform a merge of the data tables by executing filtering by user, is it possible? What should I write to perform a merge of records between tables?

Thanks

#194 mORMot 1 » Error: unrecognized token: ":" » 2011-03-11 16:02:51

corchi72
Replies: 2

Deleting a user performing the example "Synops-sqlite-demo" occurs the error: unrecognized token: ""

I added a button where I run the cancellation of the user with the following code:




procedure TForm1.btnDeleteUserClick(Sender: TObject);
begin
   Database.Delete(TSQLUser,integer(lbUsers.Items.Objects[lbUsers.ItemIndex]));
end;

debuging  I saw that goes wrong when running the following code:
function TSQLRestServerDB.EngineExecuteAll(const aSQL: RawUTF8): boolean;
begin
  try
    DB.ExecuteAll(aSQL); // Execute all statements (don't use fStatementCache[])
    result := true;
  except
    on E: ESQLException do begin
      LogToTextFile('TSQLRestServerDB.EngineExecuteAll Error: '+RawUTF8(E.Message)+#13#10+aSQL);
      result := false;
    end;
  end;
end;

#196 Re: mORMot 1 » Using SQL3 framework with MSSQL Server and / or Firebird » 2011-02-23 13:45:36

thanks,

Can I download the beta version and test it in Beta of course?

#197 mORMot 1 » Using SQL3 framework with MSSQL Server and / or Firebird » 2011-02-22 17:03:14

corchi72
Replies: 4

Sorry but I need to make this framework in sql server and / or firebir, what classes should I use to implement the components of ZEOS.


Thanks

#198 Re: mORMot 1 » Overall RTTI usage » 2011-02-02 09:50:38

I went to this link http://synopse.info/fossil/info/0088bc5396 I downloaded zip Archive: Synops OpenSource-0088bc539614c694.zip

#199 Re: mORMot 1 » Overall RTTI usage » 2011-02-02 08:54:02

Hi, when compiling the version e9cafa3892879d29 this error occurs:
"endeclared identifier : TSQLCache"

in class :

TSQLDataBase = class
  private
    fDB: TSQLite3DB;
    fFileName: TFileName;
    fTransactionActive: boolean;
    fLock: TRTLCriticalSection;
    /// if not nil, cache is used - see UseCache property
    fCache: TSQLCache;
.....

#200 Re: mORMot 1 » I would write a program that connects to multiple files in a Server. » 2011-01-31 08:46:39

ok thanks, I just tried your modification and it works very well thanks again.
Now I have to create a program that manages all the files that I want to run the server, and then be able to create client programs that connect to different server files db3.

Board footer

Powered by FluxBB