mORMot and Open Source friends
Check-in [9a55257d23]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:{2242} new AddID() function, similar to AddInt64() buf for TIDDynArray - some random GPF were identified with AddInt64(TInt64DynArray(Values),...) with the Delphi Win64 compiler
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9a55257d23db969f76d5076063b1e83fd0d05a1d
User & Date: ab 2016-01-11 14:23:24
Context
2016-01-11
15:10
{2243} Handle ftFMTBcd fields when converting a dataset into json as reported by [1dded0b992db] check-in: 1d6777278d user: ab tags: trunk
14:23
{2242} new AddID() function, similar to AddInt64() buf for TIDDynArray - some random GPF were identified with AddInt64(TInt64DynArray(Values),...) with the Delphi Win64 compiler check-in: 9a55257d23 user: ab tags: trunk
2016-01-10
19:48
{2241} small refactoring of FTS4WithoutContent feature - no functional change check-in: 6a2ccb5fb7 user: ab tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to SQLite3/mORMot.pas.

1878
1879
1880
1881
1882
1883
1884





1885
1886
1887
1888
1889
1890
1891
.....
30944
30945
30946
30947
30948
30949
30950








30951
30952
30953
30954
30955
30956
30957
30958
30959
30960
30961
30962
30963
30964
30965
30966
30967
30968
.....
30974
30975
30976
30977
30978
30979
30980
30981
30982
30983
30984
30985
30986
30987
30988
30989
.....
31047
31048
31049
31050
31051
31052
31053
31054
31055
31056
31057
31058
31059
31060
31061
31062
/// check if a TNullableUTF8Text is null, or return its value
// - returns '' if V is null or empty, or the stored UTF8-encoded text value
function NullableUTF8TextToValue(const V: TNullableUTF8Text): RawUTF8;
  overload; {$ifdef HASINLINE}inline;{$endif}

{$endif NOVARIANTS}






type
  /// the available options for TSQLRest.BatchStart() process
  // - boInsertOrIgnore will create 'INSERT OR IGNORE' statements instead of
  // plain 'INSERT' - by now, only the direct mORMotSQLite3 engine supports it
  // - boInsertOrUpdate will create 'INSERT OR REPLACE' statements instead of
  // plain 'INSERT' - by now, only the direct mORMotSQLite3 engine supports it
  // - boExtendedJSON would force the JSON to unquote the column names,
................................................................................
  fBatch.Add(',');
  result := fBatchCount;
  inc(fBatchCount);
  inc(fAddCount);
  if Assigned(fOnWrite) then
    fOnWrite(self,soInsert,PSQLRecordClass(Value)^,Value.IDValue,Value,FieldBits);
end;









function TSQLRestBatch.Delete(Table: TSQLRecordClass;
  ID: TID): integer;
begin
  if (self=nil) or (fBatch=nil) or (Table=nil) or
     (ID<=0) or not fRest.RecordCanBeUpdated(Table,ID,seDelete) then begin
    result := -1; // invalid parameters, or not opened BATCH sequence
    exit;
  end;
  AddInt64(TInt64DynArray(fDeletedRecordRef),fDeletedCount,
    fRest.Model.RecordReference(Table,ID));
  fBatch.AddShort('"DELETE@'); // '[...,"DELETE@Table",ID,...]}'
  fBatch.AddString(Table.RecordProps.SQLTableName);
  fBatch.Add('"',',');
  fBatch.Add(ID);
  fBatch.Add(',');
  result := fBatchCount;
  inc(fBatchCount);
................................................................................
function TSQLRestBatch.Delete(ID: TID): integer;
begin
  if (self=nil) or (fTable=nil) or
     (ID<=0) or not fRest.RecordCanBeUpdated(fTable,ID,seDelete) then begin
    result := -1; // invalid parameters, or not opened BATCH sequence
    exit;
  end;
  AddInt64(TInt64DynArray(fDeletedRecordRef),fDeletedCount,
    RecordReference(fTableIndex,ID));
  fBatch.AddShort('"DELETE",'); // '{"Table":[...,"DELETE",ID,...]}'
  fBatch.Add(ID);
  fBatch.Add(',');
  result := fBatchCount;
  inc(fBatchCount);
  inc(fDeleteCount);
  if Assigned(fOnWrite) then
................................................................................
    Value.ComputeFieldsBeforeWrite(fRest,seUpdate); // update sftModTime fields
  Value.GetJSONValues(fBatch);
  fBatch.Add(',');
  if fCalledWithinRest and
     (FieldBits-Props.SimpleFieldsBits[soUpdate]=[]) then
    fRest.Cache.Notify(Value,soUpdate) else
    // may not contain all cached fields -> delete from cache
    AddInt64(TInt64DynArray(fDeletedRecordRef),fDeletedCount,
      RecordReference(tableIndex,ID));
  result := fBatchCount;
  inc(fBatchCount);
  inc(fUpdateCount);
  if Assigned(fOnWrite) then
    fOnWrite(self,soUpdate,PSQLRecordClass(Value)^,Value.IDValue,Value,FieldBits);
end;







>
>
>
>
>







 







>
>
>
>
>
>
>
>









<
|







 







|
<







 







|
<







1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
.....
30949
30950
30951
30952
30953
30954
30955
30956
30957
30958
30959
30960
30961
30962
30963
30964
30965
30966
30967
30968
30969
30970
30971
30972

30973
30974
30975
30976
30977
30978
30979
30980
.....
30986
30987
30988
30989
30990
30991
30992
30993

30994
30995
30996
30997
30998
30999
31000
.....
31058
31059
31060
31061
31062
31063
31064
31065

31066
31067
31068
31069
31070
31071
31072
/// check if a TNullableUTF8Text is null, or return its value
// - returns '' if V is null or empty, or the stored UTF8-encoded text value
function NullableUTF8TextToValue(const V: TNullableUTF8Text): RawUTF8;
  overload; {$ifdef HASINLINE}inline;{$endif}

{$endif NOVARIANTS}

/// similar to AddInt64() function, but for a TIDDynArray
// - some random GPF were identified with AddInt64(TInt64DynArray(Values),...)
// with the Delphi Win64 compiler
procedure AddID(var Values: TIDDynArray; var ValuesCount: integer; Value: TID);

type
  /// the available options for TSQLRest.BatchStart() process
  // - boInsertOrIgnore will create 'INSERT OR IGNORE' statements instead of
  // plain 'INSERT' - by now, only the direct mORMotSQLite3 engine supports it
  // - boInsertOrUpdate will create 'INSERT OR REPLACE' statements instead of
  // plain 'INSERT' - by now, only the direct mORMotSQLite3 engine supports it
  // - boExtendedJSON would force the JSON to unquote the column names,
................................................................................
  fBatch.Add(',');
  result := fBatchCount;
  inc(fBatchCount);
  inc(fAddCount);
  if Assigned(fOnWrite) then
    fOnWrite(self,soInsert,PSQLRecordClass(Value)^,Value.IDValue,Value,FieldBits);
end;

procedure AddID(var Values: TIDDynArray; var ValuesCount: integer; Value: TID);
begin
  if ValuesCount=length(Values) then
    SetLength(Values,ValuesCount+256+ValuesCount shr 3);
  Values[ValuesCount] := Value;
  inc(ValuesCount);
end;

function TSQLRestBatch.Delete(Table: TSQLRecordClass;
  ID: TID): integer;
begin
  if (self=nil) or (fBatch=nil) or (Table=nil) or
     (ID<=0) or not fRest.RecordCanBeUpdated(Table,ID,seDelete) then begin
    result := -1; // invalid parameters, or not opened BATCH sequence
    exit;
  end;

  AddID(fDeletedRecordRef,fDeletedCount,fRest.Model.RecordReference(Table,ID));
  fBatch.AddShort('"DELETE@'); // '[...,"DELETE@Table",ID,...]}'
  fBatch.AddString(Table.RecordProps.SQLTableName);
  fBatch.Add('"',',');
  fBatch.Add(ID);
  fBatch.Add(',');
  result := fBatchCount;
  inc(fBatchCount);
................................................................................
function TSQLRestBatch.Delete(ID: TID): integer;
begin
  if (self=nil) or (fTable=nil) or
     (ID<=0) or not fRest.RecordCanBeUpdated(fTable,ID,seDelete) then begin
    result := -1; // invalid parameters, or not opened BATCH sequence
    exit;
  end;
  AddID(fDeletedRecordRef,fDeletedCount,RecordReference(fTableIndex,ID));

  fBatch.AddShort('"DELETE",'); // '{"Table":[...,"DELETE",ID,...]}'
  fBatch.Add(ID);
  fBatch.Add(',');
  result := fBatchCount;
  inc(fBatchCount);
  inc(fDeleteCount);
  if Assigned(fOnWrite) then
................................................................................
    Value.ComputeFieldsBeforeWrite(fRest,seUpdate); // update sftModTime fields
  Value.GetJSONValues(fBatch);
  fBatch.Add(',');
  if fCalledWithinRest and
     (FieldBits-Props.SimpleFieldsBits[soUpdate]=[]) then
    fRest.Cache.Notify(Value,soUpdate) else
    // may not contain all cached fields -> delete from cache
    AddID(fDeletedRecordRef,fDeletedCount,RecordReference(tableIndex,ID));

  result := fBatchCount;
  inc(fBatchCount);
  inc(fUpdateCount);
  if Assigned(fOnWrite) then
    fOnWrite(self,soUpdate,PSQLRecordClass(Value)^,Value.IDValue,Value,FieldBits);
end;

Changes to SQLite3/mORMotMongoDB.pas.

813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
  result := false;
  if (fCollection<>nil) and (TableModelIndex>=0) and
     (Model.Tables[TableModelIndex]=fStoredClass) and (ID>0) then
  try
    if fBatchMethod<>mNone then
      if fBatchMethod<>mDelete then
        exit else
        AddInt64(TInt64DynArray(fBatchIDs),fBatchIDsCount,ID) else begin
      if Owner<>nil then begin // notify BEFORE deletion
        Owner.InternalUpdateEvent(seDelete,TableModelIndex,ID,'',nil);
        Owner.FlushInternalDBCache;
      end;
      fCollection.RemoveOne(ID);
    end;
    result := true;






|







813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
  result := false;
  if (fCollection<>nil) and (TableModelIndex>=0) and
     (Model.Tables[TableModelIndex]=fStoredClass) and (ID>0) then
  try
    if fBatchMethod<>mNone then
      if fBatchMethod<>mDelete then
        exit else
        AddID(fBatchIDs,fBatchIDsCount,ID) else begin
      if Owner<>nil then begin // notify BEFORE deletion
        Owner.InternalUpdateEvent(seDelete,TableModelIndex,ID,'',nil);
        Owner.FlushInternalDBCache;
      end;
      fCollection.RemoveOne(ID);
    end;
    result := true;

Changes to SQLite3/mORMotSQLite3.pas.

821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
            fBatchIDMax := -1; // will force error for whole BATCH block
            exit;
          end;
        end;
        inc(fBatchIDMax);
        result := fBatchIDMax;
      end;
      AddInt64(TInt64DynArray(fBatchID),fBatchIDCount,result);
      AddRawUTF8(fBatchValues,fBatchValuesCount,SentData);
    end;
    exit;
  end;
  SQL := 'INSERT INTO '+SQL;
  if trim(SentData)='' then
    SQL := SQL+' DEFAULT VALUES;' else begin






|







821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
            fBatchIDMax := -1; // will force error for whole BATCH block
            exit;
          end;
        end;
        inc(fBatchIDMax);
        result := fBatchIDMax;
      end;
      AddID(fBatchID,fBatchIDCount,result);
      AddRawUTF8(fBatchValues,fBatchValuesCount,SentData);
    end;
    exit;
  end;
  SQL := 'INSERT INTO '+SQL;
  if trim(SentData)='' then
    SQL := SQL+' DEFAULT VALUES;' else begin

Changes to SQLite3/mORMotWrappers.pas.

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
      end else
        info := ContextFromInfo(TYPES_SIZE[itemSize]);
    end else
      info := ContextFromInfo(wUnknown,'',item);
    info.name := typName;
  end;
  end;
  if not VarIsEmptyOrNull(info) then
    list.AddItem(info);
end;
var siz: integer;
    enum: PEnumType;
begin
  if typ=wUnknown then begin
    if typInfo=nil then






|







708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
      end else
        info := ContextFromInfo(TYPES_SIZE[itemSize]);
    end else
      info := ContextFromInfo(wUnknown,'',item);
    info.name := typName;
  end;
  end;
  if not VarIsEmptyOrNull(info) then // null e.g. for a record without custom text definition
    list.AddItem(info);
end;
var siz: integer;
    enum: PEnumType;
begin
  if typ=wUnknown then begin
    if typInfo=nil then

Changes to SynopseCommit.inc.

1
'1.18.2241'
|
1
'1.18.2242'