#1 2011-07-29 10:20:14

corchi72
Member
Registered: 2010-12-10
Posts: 232

CreateAndFillPrepare(ClientDB, fIds); how to add new record

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.

Offline

#2 2011-07-29 10:33:35

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,660
Website

Re: CreateAndFillPrepare(ClientDB, fIds); how to add new record

Does it mean that a TIntegerDynArray field is not refreshed as expected, whereas standard property (like RawUTF8 or integer) is?

Offline

#3 2011-07-29 11:03:44

corchi72
Member
Registered: 2010-12-10
Posts: 232

Re: CreateAndFillPrepare(ClientDB, fIds); how to add new record

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;

Offline

#4 2011-07-29 11:25:04

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,660
Website

Re: CreateAndFillPrepare(ClientDB, fIds); how to add new record

Due to the stateless approach of the framework, there is indeed no automated reflection of the newly inserted record in the fIDs[] array.

Since all records content will already be stored as a TSQLTableJSON, you can't by design add an individual record to the list. All new list should be retrieved, by calling CreateAndFillPrepare one more time.

Is it too slow in practice? I don't think so.

Offline

#5 2011-07-29 12:22:56

corchi72
Member
Registered: 2010-12-10
Posts: 232

Re: CreateAndFillPrepare(ClientDB, fIds); how to add new record

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;

Offline

#6 2011-07-29 13:18:40

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,660
Website

Re: CreateAndFillPrepare(ClientDB, fIds); how to add new record

I guess in this later case, you'd better create a dedicated SQL query, and retrieve a TSQLTableJSON.

Offline

#7 2011-07-29 13:58:37

corchi72
Member
Registered: 2010-12-10
Posts: 232

Re: CreateAndFillPrepare(ClientDB, fIds); how to add new record

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;

Offline

#8 2011-07-29 14:42:37

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,660
Website

Re: CreateAndFillPrepare(ClientDB, fIds); how to add new record

I guess in this case, you'll have to write a dedicated SQL query, then execute it and retrieve all data using a TSQLTableJSON.

It should be much faster than all ORM-based process.
This is the limit of ORM, and, as stated by the documentation, it could be a proper occasion to switch back to SQL.

Offline

Board footer

Powered by FluxBB