Browse Source

fcl-db: bufdataset: when data are written to BLOB field (using TBufBlobStream) then unset field null flag when blob stream is created. When writting finishes (on destroy of blob stream) set null flag if blob is empty. + updated test TestChangeBlob. Bug #15376

git-svn-id: trunk@27089 -
lacak 11 years ago
parent
commit
742c590a3a
2 changed files with 20 additions and 19 deletions
  1. 13 17
      packages/fcl-db/src/base/bufdataset.pas
  2. 7 2
      packages/fcl-db/tests/testfieldtypes.pas

+ 13 - 17
packages/fcl-db/src/base/bufdataset.pas

@@ -2422,7 +2422,7 @@ procedure TCustomBufDataset.InternalCancel;
 Var i            : integer;
 Var i            : integer;
 
 
 begin
 begin
-  if assigned(FUpdateBlobBuffers) then for i:=0 to length(FUpdateBlobBuffers)-1 do
+  if assigned(FUpdateBlobBuffers) then for i:=0 to high(FUpdateBlobBuffers) do
     if assigned(FUpdateBlobBuffers[i]) and (FUpdateBlobBuffers[i]^.FieldNo>0) then
     if assigned(FUpdateBlobBuffers[i]) and (FUpdateBlobBuffers[i]^.FieldNo>0) then
       FreeBlobBuffer(FUpdateBlobBuffers[i]);
       FreeBlobBuffer(FUpdateBlobBuffers[i]);
 end;
 end;
@@ -2431,26 +2431,14 @@ procedure TCustomBufDataset.InternalPost;
 
 
 Var ABuff        : TRecordBuffer;
 Var ABuff        : TRecordBuffer;
     i            : integer;
     i            : integer;
-    bufblob      : TBufBlobField;
-    NullMask     : pbyte;
     ABookmark    : PBufBookmark;
     ABookmark    : PBufBookmark;
 
 
 begin
 begin
   inherited InternalPost;
   inherited InternalPost;
 
 
-  if assigned(FUpdateBlobBuffers) then for i:=0 to length(FUpdateBlobBuffers)-1 do
+  if assigned(FUpdateBlobBuffers) then for i:=0 to high(FUpdateBlobBuffers) do
    if assigned(FUpdateBlobBuffers[i]) and (FUpdateBlobBuffers[i]^.FieldNo>0) then
    if assigned(FUpdateBlobBuffers[i]) and (FUpdateBlobBuffers[i]^.FieldNo>0) then
-    begin
-    bufblob.BlobBuffer := FUpdateBlobBuffers[i];
-    NullMask := PByte(ActiveBuffer);
-
-    if bufblob.BlobBuffer^.Size = 0 then
-      SetFieldIsNull(NullMask, bufblob.BlobBuffer^.FieldNo-1)
-    else
-      unSetFieldIsNull(NullMask, bufblob.BlobBuffer^.FieldNo-1);
-
-    bufblob.BlobBuffer^.FieldNo := -1;
-    end;
+    FUpdateBlobBuffers[i]^.FieldNo := -1;
 
 
   if State = dsInsert then
   if State = dsInsert then
     begin
     begin
@@ -2764,8 +2752,11 @@ begin
       else
       else
         FBlobBuffer^.OrgBufID := -1;
         FBlobBuffer^.OrgBufID := -1;
       bufblob.BlobBuffer := FBlobBuffer;
       bufblob.BlobBuffer := FBlobBuffer;
-      // redirect pointer in current record buffer to new write blob buffer
+
       CurrBuff := GetCurrentBuffer;
       CurrBuff := GetCurrentBuffer;
+      // unset null flag for blob field
+      unSetFieldIsNull(PByte(CurrBuff), Field.FieldNo-1);
+      // redirect pointer in current record buffer to new write blob buffer
       inc(CurrBuff, FDataSet.FFieldBufPositions[Field.FieldNo-1]);
       inc(CurrBuff, FDataSet.FFieldBufPositions[Field.FieldNo-1]);
       Move(bufblob, CurrBuff^, FDataSet.GetFieldSize(FDataSet.FieldDefs[Field.FieldNo-1]));
       Move(bufblob, CurrBuff^, FDataSet.GetFieldSize(FDataSet.FieldDefs[Field.FieldNo-1]));
       FModified := True;
       FModified := True;
@@ -2777,11 +2768,16 @@ begin
   if FModified then
   if FModified then
     begin
     begin
     // if TBufBlobStream was requested, but no data was written, then Size = 0;
     // if TBufBlobStream was requested, but no data was written, then Size = 0;
-    //  used by TBlobField.Clear, so in this case set Field to null in InternalPost
+    //  used by TBlobField.Clear, so in this case set Field to null
     //FField.Modified := True; // should be set to True, but TBlobField.Modified is never reset
     //FField.Modified := True; // should be set to True, but TBlobField.Modified is never reset
 
 
     if not (FDataSet.State in [dsFilter, dsCalcFields, dsNewValue]) then
     if not (FDataSet.State in [dsFilter, dsCalcFields, dsNewValue]) then
+      begin
+      if FBlobBuffer^.Size = 0 then // empty blob = IsNull
+        // blob stream should be destroyed while DataSet is in write state
+        SetFieldIsNull(PByte(FDataSet.GetCurrentBuffer), FField.FieldNo-1);
       FDataSet.DataEvent(deFieldChange, PtrInt(FField));
       FDataSet.DataEvent(deFieldChange, PtrInt(FField));
+      end;
     end;
     end;
   inherited Destroy;
   inherited Destroy;
 end;
 end;

+ 7 - 2
packages/fcl-db/tests/testfieldtypes.pas

@@ -608,9 +608,7 @@ begin
 end;
 end;
 
 
 procedure TTestFieldTypes.TestChangeBlob;
 procedure TTestFieldTypes.TestChangeBlob;
-
 var s : string;
 var s : string;
-
 begin
 begin
   TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (ID int,FT '+FieldtypeDefinitions[ftblob]+')');
   TSQLDBConnector(DBConnector).Connection.ExecuteDirect('create table FPDEV2 (ID int,FT '+FieldtypeDefinitions[ftblob]+')');
   TSQLDBConnector(DBConnector).CommitDDL;
   TSQLDBConnector(DBConnector).CommitDDL;
@@ -633,6 +631,13 @@ begin
     Cancel;
     Cancel;
     AssertEquals('After Cancel', 'Test this blob', Fields[1].AsString); // original value
     AssertEquals('After Cancel', 'Test this blob', Fields[1].AsString); // original value
 
 
+    Append; // Blob is null
+    Fields[1].AsString := s; // Null flag must be unset
+    AssertEquals(s, Fields[1].AsString);
+    Fields[1].Clear;
+    AssertTrue('Clear', Fields[1].IsNull);
+    Cancel;
+
     Edit;
     Edit;
     With CreateBlobStream(Fields[1], bmWrite) do
     With CreateBlobStream(Fields[1], bmWrite) do
       begin
       begin