#1 2023-06-11 11:31:34

damiand
Member
From: Greece
Registered: 2018-09-21
Posts: 94

Apply CDS updates to rest server

I have a TClientDataSet instance created via the ToClientDataSet function of the mormot.db.rad.ui.cds unit:

  status := TStatus.CreateAndFillPrepare(restClient.Orm,'');
  dsStatus.DataSet := ToClientDataSet(Self, status.FillTable, restClient);

dsStatus is a TDataSource component linked to a DBGrid on a form. How can I apply the updates in the grid back to database? The following has no effect:

  if (dsStatus.DataSet is TClientDataSet) and dsStatus.DataSet.Active then
     TClientDataSet(dsStatus.DataSet).ApplyUpdates(0);

Offline

#2 2023-06-12 06:59:56

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

Re: Apply CDS updates to rest server

Using FPC or Delphi ?

Offline

#3 2023-06-12 07:06:54

damiand
Member
From: Greece
Registered: 2018-09-21
Posts: 94

Re: Apply CDS updates to rest server

Delphi

Offline

#4 2023-06-12 07:32:04

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

Re: Apply CDS updates to rest server

I just checked, this feature was not yet moved from mORMot 1 SynDBMidasVCL.pas unit.

https://github.com/synopse/mORMot2/commit/1753e609

Offline

#5 2023-06-12 09:26:52

damiand
Member
From: Greece
Registered: 2018-09-21
Posts: 94

Re: Apply CDS updates to rest server

Thanks, but the problem persists. So I presume that the above commit just documents the missing code and doesn't port it into mormot2?

Last edited by damiand (2023-06-12 09:29:10)

Offline

#6 2023-06-12 12:10:42

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

Re: Apply CDS updates to rest server

I have implemented a writable TSqlDBClientDataSet inheriting from TClientDataSet.
See https://github.com/synopse/mORMot2/commit/7a949a0b

BUT it is not for ORM data access, but for raw mormot.db.sql updates - as with moRMot 1.

Offline

#7 2023-06-13 01:38:58

cybexr
Member
Registered: 2016-09-14
Posts: 78

Re: Apply CDS updates to rest server

maybe this function helps

in-cds, your clientdataset  contains modified data
in-rest  clientrest,  funciton will loop all cds delta (insert update delete),  then invoke rest-batch uri call
in-oc tableOrmclass

function YGGCDSApplyREST(cds: TClientDataSet; const rest: TRestClientURI; oc: TOrmClass):Boolean;
var
  prev: record
    BM: TBookMark;
    Active: Boolean;
    ReadOnly: Boolean;
    LogChanges: Boolean;
    AfterScroll: TDataSetNotifyEvent;
  end;

  change: TClientDataset;
  o: TOrm;
  m,n :integer;
  del: TID;
  IDs: TIDDynArray;
  insertBatchIdx: Array of Integer;

  insertBM: Array of TBookMark;
  batch : TRestBatch;
  UpdateCSV: RawUTF8;

  function oprops(isUpdate: Boolean): RawUTF8;
  var
    f: integer;
    fn: String;
    v: Variant;
    u: RawUTF8;
  begin
    Result:= '';  //csv, updated fields.  eg   FP_Name,FP_Code
    for f := 0 to cds.Fields.Count-1 do
    begin
      fn:= ( cds.Fields[f].FieldName );
      u:= LowerCase( StringToUTf8(fn) );
      if SameText(UpperCase(fn), 'ID') then continue;         // skip id

      if isUpdate and (
         VarSameValue(
           cds.Fields[f].OldValue,
           cds.Fields[f].NewValue)
        ) then Continue;                   //skip field if not modify

      v:= cds.Fields[f].Value;
      if (1=1) and
         (o.OrmProps.Fields.ByRawUtf8Name(u).OrmFieldType = oftUtf8Text) and
         ( (cds.Fields[f].DataType= ftString) or
           (cds.Fields[f].DataType= ftWideString) ) and
         Varisnull(v)  then
        ClearVariantForString(v);

      o.SetFieldVariant(fn, v);
      AddToCsv(u, Result);
    end;
  end;
begin
  Result:= False;
  if cds.ChangeCount =0 then Exit;

  Prev.BM:= cds.Bookmark;
  prev.AfterScroll:= cds.AfterScroll;
  cds.AfterScroll:=nil;

  change := TClientDataset.Create(nil);
  batch := TRestBatch.Create(rest.Orm, oc);
  try
    SetLength(insertBatchIdx, 0);

    rest.BatchStartAny(0);

    cds.First;
    while not cds.Eof do
    begin
      case cds.UpdateStatus of
        usUnmodified: begin


          end;
        usModified: begin
            o:= oc.Create;
            try
              o.IDValue:= cds.FieldByName('ID').AsInteger;
              UpdateCSV:= oprops(True);
              batch.Update(o, UpdateCSV);
            finally
              o.Free;
            end;
          end;
        usInserted: begin
            o:= oc.Create;
            try
            oprops(False);

            SetLength(insertBatchIdx , Length(insertBatchIdx)+1);
            insertBatchIdx[Length(insertBatchIdx)-1]:=
              batch.Add(o, True);

            SetLength(insertBM , Length(insertBM)+1);
            insertBM[Length(insertBM)-1]:= cds.GetBookmark;
            finally
              o.Free;
            end;
          end;
        usDeleted: begin
          end;
      end;

      cds.Next;
    end;

    Change.Data:= cds.Delta;
    Change.First;
    while not Change.Eof do
    begin
      case Change.UpdateStatus of
        usDeleted: begin
            del:= Change.FieldByName('ID').OldValue;
            batch.Delete(del);
          end;
      end;
      Change.Next;
    end;

    Result:= rest.Orm.BatchSend(batch, IDs) = HTTP_SUCCESS;
    if not Result then
      DatabaseError(UTF8ToString(rest.LastErrorMessage));

    if Length(insertBatchIdx) >0  then begin          // fill REST-Returned Inserted IDs
      Change.Data:= cds.Data;
      Change.LogChanges:= False;
      Change.MergeChangeLog;

      for m := Low(IDS) to High(IDs) do       //  [200, 200, 15,16,17, 404]
      begin
        for n:= Low(insertBatchIdx) to High(insertBatchIdx) do        // [2,3,4]
          if m= insertBatchIdx[n] then
          begin
            Change.Bookmark:= insertBM[m];

            Change.Edit;
            Change.FieldByName('ID').AsInteger:= IDS[m];
            Change.Post;
          end;
      end;
      cds.Data:= Change.Data;
    end;

    if Assigned(Prev.BM) then
      cds.Bookmark:= Prev.BM;

    Result:= True;
  finally
    cds.AfterScroll:= prev.AfterScroll;

    batch.Free;
    change.Free;
  end;

end;

Offline

Board footer

Powered by FluxBB