Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2005-07

Patch to remove useless bookmark store in TDataset.DoInsertAppend

6 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Luiz Américo

As already commented in the code, the bookmarking done inside TDataset.DoInsertAppend is useless, not to say buggy. It makes 2 records to have the same bookmark data but this is not noticed because the bookmarkdata is set to the correct value after Post->Resync.

In TDBF, if the bookmark is get just after a insert call this bookmark will point to the previous record (see the attached example).

The patch remove this code and also refactory a if statement.

Unfortunately, after applying the patch if a bookmark is get after insert this bookmark points to the first record. This occurs because TDBF inits a buffer with BookMarkData=0 and BookMarkFlag=bfCurrent instead of bfInserted (this makes bookmarkavailable returns true)

As far as i can understand it seems that is not allowed to get a bookmark in a not posted record, is it?

BTW is necessary/correct the SetBookMarkFlag call (inside DoInsert) in this procedure ?

Luiz

Reply by email

Joost van der Sluis
to Luiz Américo
Luiz Américo wrote 5 lines
As already commented in the code, the bookmarking done inside TDataset.DoInsertAppend is useless, not to say buggy. It makes 2 records to have the same bookmark data but this is not noticed because the bookmarkdata is set to the correct value after Post->Resync.

I didn't dare to remove it, it could give strange results...

Show quoted text 12 lines
In TDBF, if the bookmark is get just after a insert call this bookmark will point to the previous record (see the attached example). The patch remove this code and also refactory a if statement. Unfortunately, after applying the patch if a bookmark is get after insert this bookmark points to the first record. This occurs because TDBF inits a buffer with BookMarkData=0 and BookMarkFlag=bfCurrent instead of bfInserted (this makes bookmarkavailable returns true) As far as i can understand it seems that is not allowed to get a bookmark in a not posted record, is it?

Maybe that if the record is posted, it get a new bookmark? Can you test that? If that's so, i would say we could apply your patch, and look if someone reports that there's something broken...

Met vriendelijke groeten, Joost van der Sluis CNOC Informatiesystemen en Netwerken http://www.cnoc.nl

Reply by email

Alexandrov Alexandru
to Luiz Américo: As already commented in the code, the bookmarking done inside TDataset.DoInsertAppend is…
Luiz Américo wrote 18 lines
As already commented in the code, the bookmarking done inside TDataset.DoInsertAppend is useless, not to say buggy. It makes 2 records to have the same bookmark data but this is not noticed because the bookmarkdata is set to the correct value after Post->Resync. In TDBF, if the bookmark is get just after a insert call this bookmark will point to the previous record (see the attached example). The patch remove this code and also refactory a if statement. Unfortunately, after applying the patch if a bookmark is get after insert this bookmark points to the first record. This occurs because TDBF inits a buffer with BookMarkData=0 and BookMarkFlag=bfCurrent instead of bfInserted (this makes bookmarkavailable returns true) As far as i can understand it seems that is not allowed to get a bookmark in a not posted record, is it?

You can bookmark at any time. But as the inserted record is not posted yet, the bookmark will point to the current record in dataset. Multiple users can insert records at same time.

Show quoted text 73 lines
BTW is necessary/correct the SetBookMarkFlag call (inside DoInsert) in this procedure ? Luiz program testbookdbf; {$Mode ObjFpc} {$H+} uses sysutils,classes,db,dbf; var Counter:Integer; FDataset:TDbf; Book0,Book1:TBookMarkStr; begin //Main FDataSet:=TDbf.Create(nil); with FDataSet do begin FilePathFull:=ExtractFilePath(ParamStr(0)); Tablename:='dbf_book.db'; if FileExists(FilePathFull+TableName) then DeleteFile(FilePathFull+TableName); if not FileExists(FilePathFull+TableName) then begin FieldDefs.Clear; FieldDefs.Add('Int',ftInteger); FieldDefs.Add('Str',ftString); CreateTable; end; Open; //add 2 records Insert; FieldByName('Int').AsInteger:=-1; FieldByName('Str').AsString:='minus'; Post; Insert; FieldByName('Int').AsInteger:=0; FieldByName('Str').AsString:='zero'; Post; Book0:=Bookmark; Insert; Book1:=Bookmark; FieldByName('Int').AsInteger:=1; FieldByName('Str').AsString:='one'; Post; Book1:=Bookmark; //Comment this to get the error //Now go to bookmarks Last; writeln('Record before going to books: ',FieldByName('Int').AsInteger); BookMark:=Book1; writeln('Bookmark set to book1'); writeln('Current Record: ',FieldByName('Int').AsInteger); BookMark:=Book0; writeln('Bookmark set to book0'); writeln('Current Record: ',FieldByName('Int').AsInteger); Free; end; end. _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

This example is bad. See above.

Most datasets don't allow inserting records. Including TDbf. If a dataset allow to insert records, and if the bookmark is the same as record number, then the new record must have the same bookmark as the old record.
Next records bookmarks must be changed.
If the record is appended, after DoInsert, follow
SetBookmarkFlag(ActiveBuffer,bfEOF);
It is ok i think.

Alex

Reply by email

Luiz Américo
to Alexandrov Alexandru
Alexandrov Alexandru wrote 23 lines
On 7/24/05, Luiz Américo wrote: >As already commented in the code, the bookmarking done inside >TDataset.DoInsertAppend is useless, not to say buggy. >It makes 2 records to have the same bookmark data but this is not >noticed because the bookmarkdata is set to the correct value after >Post->Resync. > >In TDBF, if the bookmark is get just after a insert call this bookmark >will point to the previous record (see the attached example). > >The patch remove this code and also refactory a if statement. > >Unfortunately, after applying the patch if a bookmark is get after >insert this bookmark points to the first record. This occurs because >TDBF inits a buffer with BookMarkData=0 and BookMarkFlag=bfCurrent >instead of bfInserted (this makes bookmarkavailable returns true) > >As far as i can understand it seems that is not allowed to get a >bookmark in a not posted record, is it? You can bookmark at any time.

No, see BookMarkAvailable function in TDataSet: it return true only when there's a record and when BookMarkFlag= bfCurrent. After a insert, in TBufDataset at least, the bookmarkFlag is set to bfInserted, so if a user try to BookMark after a insert/append and before Post, the BookMark will be nil.

But as the inserted record is not posted yet, the bookmark will point to the current record in dataset.

See above

Multiple users can insert records at same time.

Sql based TDataSet keeps a cache of the data, inserting in the dataset will only modify the cache. The conflict of multiuser changing records can rise when the changes are sent to the database not when manipulating the cache.

BTW: TDbf allows multiple accesses?

This example is bad. See above. Most datasets don't allow inserting records. Including TDbf.

It's also valid for append. Anyway it's not possible to get a BookMark after a append because of the BookMarkFlag (bfEOf).

If a dataset allow to insert records, and if the bookmark is the same as record number, then the new record must have the same bookmark as the old record. Next records bookmarks must be changed.

Ok. But's up to the TDataset descendant do this in InternalInsert

If the record is appended, after DoInsert, follow SetBookmarkFlag(ActiveBuffer,bfEOF); It is ok i think.

Luiz

Reply by email

Gerhard Scholz
to Luiz Américo

I have tried to put this into the bug list but got an error message (I have put that error into the buglist: bug# 4228), so I have to put it in the mailing list, sorry.

Bug while evaluating macros:

Compilerversion of 25.7.2005 has error (18.7.2005 works!)

{$note hello1}
{$if sizeof ( integer ) = 2 }
  {$ifdef BCDgr4 }
                                  VAR
                                    myMinIntBCD : tBCD ;
  {$endif}
{$else}
{$note hello2}
  {$if sizeof ( integer ) = 4 }
{$note hello2a}
    {$ifdef BCDgr9 }
{$note hello2b}
                                  VAR
                                    myMinIntBCD : tBCD ;
    {$endif}
  {$else}
    {$if sizeof ( integer ) = 8 }
      {$ifdef BCDgr18 }
                                  VAR
                                    myMinIntBCD : tBCD ;
      {$endif}
    {$else}
      {$fatal You have an interesting integer type! Sorry, not supported}
    {$endif}
  {$endif}
{$endif}
{$note hello3}

The sizeof ( integer ) = 4 produces the error:

22:55:40 P:\FmtBCD>ppc386 -al -Croit -Cs700000 -Op1 fmtbcdgs Free Pascal Compiler version 2.1.1 [2005/07/25] for i386 Copyright (c) 1993-2005 by Florian Klaempfl
Note: Switching assembler to default source writing assembler Target OS: Win32 for i386
Compiling fmtbcdgs.pas
fmtbcdgs.pas(10,66) Warning: Comment level 2 found fmtbcdgs.pas(13,6) Warning: Comment level 2 found
fmtbcdgs.pas(13,46) Warning: Comment level 2 found fmtbcdgs.pas(52,3) Note: User defined: BCD Digits > 4 fmtbcdgs.pas(56,3) Note: User defined: BCD Digits > 9 fmtbcdgs.pas(60,3) Note: User defined: BCD Digits > 18 fmtbcdgs.pas(64,3) Note: User defined: BCD Digits > 64 fmtbcdgs.pas(68,3) Note: User defined: BCD Digits > 180 fmtbcdgs.pas(192,4) Note: User defined: ansi
fmtbcdgs.pas(807,3) Warning: Comment level 2 found fmtbcdgs.pas(808,3) Warning: Comment level 2 found fmtbcdgs.pas(963,2) Note: User defined: hello1
fmtbcdgs.pas(970,2) Note: User defined: hello2
fmtbcdgs.pas(971,7) Fatal: Compilation aborted
An unhandled exception occurred at $00421661 :
EAccessViolation : Access violation
$00421661 SEARCHSYM, line 1833 of symtable.pas
$00476FDC READ_FACTOR, line 580 of scanner.pas
$00476A8B READ_TERM, line 739 of scanner.pas
$0047695B READ_SIMPLE_EXPR, line 764 of scanner.pas $00476543 READ_EXPR, line 790 of scanner.pas
$004764E8 PARSE_COMPILER_EXPR, line 843 of scanner.pas $00477951 BOOLEAN_COMPILE_TIME_EXPR, line 850 of scanner.pas $00479AE5 TSCANNERFILE__IFPREPROCSTACK, line 1674 of scanner.pas $004779BB DIR_IF, line 857 of scanner.pas
$00479E22 TSCANNERFILE__HANDLECONDITIONAL, line 1756 of scanner.pas $0047A1ED TSCANNERFILE__HANDLEDIRECTIVES, line 1849 of scanner.pas $0047AD59 TSCANNERFILE__SKIPCOMMENT, line 2349 of scanner.pas $0047B071 TSCANNERFILE__READTOKEN, line 2492 of scanner.pas $004852F4 CONSUME, line 137 of pbase.pas
$0048F674 READ_PROC, line 1284 of psub.pas
$0048FA22 READ_DECLARATIONS, line 1374 of psub.pas $0048CCA8 BLOCK, line 161 of psub.pas

I assume it has something to do with the withsymtable (weren't there changes?)

I was not able to construct a short example; when I shortened to a simple example it did work. So the full code can be found on http://g--s.de/pas/fmtbcdgs.pas (sorry, 112 kB!)

Solution for the moment: to go back to the FPC version of 18.7.2005

Reply by email