#1 2020-12-11 16:30:35

leus
Member
Registered: 2012-09-05
Posts: 79

Batch update based on ID

I have some operations that require an update on a list of records that I retrieved from the database before.

In essence, I have a list of IDs that I need to update a single field. I've looking at TSQLRestBatch, but that needs the whole record loaded, I believe.

Is there a way to update a single field in a list of record Ids?

(Slowly making progress - by the way, when doing Google searchs, I get flooded with commit messages from Fossil, I think that should be addressed).

Offline

#2 2020-12-11 17:47:53

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

Re: Batch update based on ID

No, you can specify the field name(s) to be updates in the batch.

Offline

#3 2020-12-11 19:22:32

Vitaly
Member
From: UAE
Registered: 2017-01-31
Posts: 168
Website

Re: Batch update based on ID

If I understood it correctly, I guess, you can try smth like (not tested)

LBatch := TSQLRestBatch.Create(YourRestDB, nil, 1000);
LRecord := TSQLYourRecordClass.Create;
LRecord.FieldToUpdate := NewValue;
for i := 0 to IDsCount - 1 do
begin
LRecord.IDValue := IDs[i];
LBatch.Update(LRecord, 'FieldToUpdate');
end;
FreeAndNil(LRecord);
YourRestDB.BatchSend(LBatch);
FreeAndNil(LBatch);

But if it is possible, I would use a direct sql statement for such case, although sometimes it is not the best decision of course.

Offline

#4 2020-12-11 19:53:01

leus
Member
Registered: 2012-09-05
Posts: 79

Re: Batch update based on ID

Thanks, that really helps.

Anyways, apparently I'm doing something wrong, because the "Add" method always exits because fails this check:

if PSQLRecordClass(Value)^<>fTable then
      exit else begin // '{"Table":[...,"PUT",{object},...]}'

The debugger evaluates PSQLRecordClass(Value)^ as TSQLRecordClass($204B0) (my record class derives from TSQLRecord).

What should I use to fix this?

Last edited by leus (2020-12-11 19:54:07)

Offline

#5 2020-12-11 20:57:57

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

Re: Batch update based on ID

You did specify an improper class to the TSQLRestBatch.Create() constructor.
If you specify a class here, you need to stick to this class.
I guess you update several types of classes in your batch, but you specified a given one in the constructor.

Offline

#6 2020-12-11 21:42:20

leus
Member
Registered: 2012-09-05
Posts: 79

Re: Batch update based on ID

I was about to post my code, and found out that effectively, I was using the wrong object during the update.

This is my current code, which seems to be working fine:

procedure UpdateTrackIds(docs: TSomeList; TrackId: Int64);
var
  batchUpdater: TSQLRestBatch;
  i: Integer;
  fieldBits: TSQLFieldBits;
  rec: TMyRecord;
begin
  fieldBits := TMyRecord.RecordProps.FieldBitsFromRawUTF8
    ([StringToUTF8('TrackId')]);
  batchUpdater := TSQLRestBatch.Create(ServerDB, TMyRecord);
  try
    rec := TMyRecord.Create;
    try
      rec.TrackId := TrackId;
      for i := 0 to Length(docs) - 1 do
      begin
        rec.IDValue := docs[i].Id;
        batchUpdater.Update(rec, fieldBits);
      end;
    finally
      rec.Free;
    end;
    ServerDB.BatchSend(batchUpdater);
  finally
    batchUpdater.Free;
  end;
end;

Last edited by leus (2020-12-11 21:42:39)

Offline

#7 2020-12-11 21:46:15

macfly
Member
From: Brasil
Registered: 2016-08-20
Posts: 374

Re: Batch update based on ID

Interesting this solution.

But in relation to the cache.
Will the framewok recognize these updates and update/clear the cache?

Offline

#8 2020-12-11 22:04:51

Vitaly
Member
From: UAE
Registered: 2017-01-31
Posts: 168
Website

Re: Batch update based on ID

Probably this is the answer to your question:

    // - if not all fields are specified, will reset the cache entry associated
    // with this value, unless ForceCacheUpdate is TRUE
    function Update(Value: TSQLRecord; const CustomFields: TSQLFieldBits=[];
      DoNotAutoComputeFields: boolean=false; ForceCacheUpdate: boolean=false): integer; overload; virtual;

Offline

#9 2020-12-11 22:13:29

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

Re: Batch update based on ID

Note that

StringToUTF8('TrackId')

is not needed - you can use a 'TrackID' constant with no problem.

Offline

#10 2020-12-11 22:24:44

macfly
Member
From: Brasil
Registered: 2016-08-20
Posts: 374

Re: Batch update based on ID

Thanks @Vitaly

Offline

#11 2020-12-12 11:10:53

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

Re: Batch update based on ID

Warning: ForceCacheUpdate may be misleading.

If there are all fields available in the batch update, then the ORM update the cache properly.
If there are some missing fields (e.g. in your case if you only update one field), then it won't update the cache, it will just reset the cache for this entry.

Setting ForceCacheUpdate will replace the value in cache with the updated fields only.
In your case, if you make a Retrieve per ID, you will have ONLY the update field set.
Not what you expect for sure.

So, the cache is always properly set or reset. You do'nt have to worry about it.
ForceCacheUpdate is not to be used in your case.

See the TSQLRestBatch.Update method code as reference.

Offline

#12 2020-12-12 15:53:13

leus
Member
Registered: 2012-09-05
Posts: 79

Re: Batch update based on ID

I don't understand. Should I worry about cache updates? If another client retrieves any of the updated records right after this method is executed, will they get the updated ID?

Offline

#13 2020-12-12 17:02:08

macfly
Member
From: Brasil
Registered: 2016-08-20
Posts: 374

Re: Batch update based on ID

Do not worry.
This was a question I had, but it was explained above.

Leave the default value ForceCacheUpdate = False and it should be OK.

Offline

#14 2020-12-12 17:08:50

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

Re: Batch update based on ID

ab wrote:

So, the cache is always properly set or reset. You do'nt have to worry about it.
ForceCacheUpdate is not to be used in your case.

Offline

Board footer

Powered by FluxBB