Page 1 of 1
BookmarkValid in version 6.7.13
Posted: Sat 27 Apr 2013 09:55
by Romano
Hi,
I looked at your solution for BookmarkValid.
I'm not sure that it is ok. If I compare it with conditions in SetToBookmark and CompareBookmarks I think that it could be write in another way...
Code: Select all
procedure TMemData.SetToBookmark(Bookmark: PRecBookmark);
...
if (Bookmark.RefreshIteration = FRefreshIteration) and
(IntPtr(Bookmark.Item) <> nil)
then begin
....
end;
// Set by order
inherited;
end;
Code: Select all
function TMemData.CompareBookmarks(Bookmark1, Bookmark2: PRecBookmark): integer;
...
if Bookmark1.RefreshIteration = Bookmark2.RefreshIteration then
if Bookmark1.Item = Bookmark2.Item then begin
...
if (IntPtr(Bookmark1.Item) <> nil) and (IntPtr(Bookmark2.Item) <> nil) then
try // for freed item
if Bookmark1.Item.Order >= Bookmark2.Item.Order then
if Bookmark1.Item.Order = Bookmark2.Item.Order then
...
// Compare by order
Result := inherited CompareBookmarks(Bookmark1, Bookmark2);
end;
I think that the right condition in BookmarkValid is:
Code: Select all
function TMemData.BookmarkValid(Bookmark: PRecBookmark): boolean;
begin
if IntPtr(Bookmark) <> nil then
begin
if (Bookmark.RefreshIteration = FRefreshIteration) and (IntPtr(Bookmark.Item) <> nil) then
Result := (Bookmark.Item.Order <= FRecordCount)
else
Result := (Bookmark.Order <> -1) and (Bookmark.Order <= FRecordCount);
end
else
Result := False;
if Result and Filtered then
Result := not OmitRecord(Bookmark.Item);
end;
Maybe I'm wrong:-), but we have problem with BookamrkValid in combination with grid from Developer Express and the right solution is crucial for as and our customers...
Thanks
Roman Krupicka
Re: BookmarkValid in version 6.7.13
Posted: Mon 29 Apr 2013 10:39
by AndreyZ
Hello,
Please describe in details the problem you encountered with using SDAC and grid from DevExpress.
Re: BookmarkValid in version 6.7.13
Posted: Mon 29 Apr 2013 13:19
by Romano
Hi,
problem was with Access Violation Error. You have fixed it in 6.7.13. I was curious how you fixed it. That's all:-).
But if I see condition for BookmarkValid I have question - is the condition right?
You compare RefreshIteration and Item at first in SetToBookmark and CompareBookmarks. And after it Order:
Code: Select all
procedure TMemData.SetToBookmark(Bookmark: PRecBookmark);
...
if (Bookmark.RefreshIteration = FRefreshIteration) and
(IntPtr(Bookmark.Item) <> nil)
then begin
....
end;
// Set by order
inherited;
end;
But in BookmarkValid you compare Order at first and if it is False, you compare RefreshIteration and Item. I think that the condition should be vice versa...
Code: Select all
if IntPtr(Bookmark) <> nil then
Result := ((Bookmark.Order <> -1) and (Bookmark.Order <= FRecordCount)) or
((Bookmark.RefreshIteration = FRefreshIteration) and (IntPtr(Bookmark.Item) <> nil) and (Bookmark.Item.Order <= FRecordCount))
else
Result := False;
Your condition:
1. step - ORDER
Result := ((Bookmark.Order <> -1) and (Bookmark.Order <= FRecordCount))
or
2. step - RefreshIteration and Item
((Bookmark.RefreshIteration = FRefreshIteration) and (IntPtr(Bookmark.Item) <> nil) and (Bookmark.Item.Order <= FRecordCount))
My suggestion:
Code: Select all
function TMemData.BookmarkValid(Bookmark: PRecBookmark): boolean;
begin
if IntPtr(Bookmark) <> nil then
begin
// 1. step - RefreshIteration and Item
if (Bookmark.RefreshIteration = FRefreshIteration) and
(IntPtr(Bookmark.Item) <> nil) then
Result := (Bookmark.Item.Order <= FRecordCount)
else
// 2. step - ORDER
Result := (Bookmark.Order <> -1) and (Bookmark.Order <= FRecordCount);
end
else
Result := False;
end;
Regards
Roman Krupicka
Re: BookmarkValid in version 6.7.13
Posted: Tue 30 Apr 2013 06:02
by colek
I agree with the colleague Roman. BookmarkValid does not return the correct value in some cases.
Please, look at the example (just click on the Button2).
Regards
Martin Kolek
Project1
Code: Select all
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Unit1
Code: Select all
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DB, MemDS, DBAccess, MSAccess;
type
TForm1 = class(TForm)
Connection: TMSConnection;
Query: TMSQuery;
Button2: TButton;
Label3: TLabel;
lPocet2: TLabel;
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses
MemData;
{$R *.dfm}
procedure TForm1.Button2Click(Sender: TObject);
function __GetQueryStr(PocetZaznamu: integer): string;
function __RandomChar: string;
begin
Result := Chr(65 + Random(26));
end;
function __RandomWord(PocetPismen: integer): string;
var
i: integer;
begin
Result := '';
for i := 0 to PocetPismen - 1 do
Result := Result + __RandomChar;
end;
var
i: integer;
begin
Randomize;
Result := 'SELECT * FROM (';
for i := 0 to PocetZaznamu - 1 do
begin
if i = 0 then
Result := Result +
Format(
'(SELECT %d AS Field1, ''%s'' AS Field2, ''%s'' AS Field3, ''%s'' AS Field4)',
[Random(1000),
__RandomWord(3),
__RandomWord(2),
__RandomWord(1)])
else
Result := Result +
Format(
'(SELECT %d, ''%s'', ''%s'', ''%s'')',
[Random(1000),
__RandomWord(3),
__RandomWord(2),
__RandomWord(1)]);
if i < (PocetZaznamu - 1) then
Result := Result + ' UNION ALL'#13
end;
Result := Result + ') t';
end;
var
B: TBookmark;
begin
Connection.Connect;
Query.SQL.Text := __GetQueryStr(10);
Query.Open;
Query.Last;
B := Query.Bookmark;
Query.Close;
Query.SQL.Text := __GetQueryStr(100);
Query.Open;
if Query.BookmarkValid(B) then
ShowMessage('Ooops, invalid bookmark is valid!');
lPocet2.Caption := IntToStr(StrToIntDef(lPocet2.Caption, 0) + 1);
lPocet2.Refresh;
end;
end.
Re: BookmarkValid in version 6.7.13
Posted: Tue 30 Apr 2013 08:54
by AndreyZ
To colek:
It is a correct behaviour that BookmarkValid returns True in your example, because there is a valid record the B bookmark points to. The code that Romano suggests will return the same result.
To Romano:
We think that our code is correct. If you encounter any situations when BookmarkValid returns incorrect value, please describe it in details (particularly, why you think the value is incorrect).
Re: BookmarkValid in version 6.7.13
Posted: Tue 07 May 2013 12:03
by Romano
Hi,
question is what is it bookmark...
I think that bookmark is unique identification of row in query.
So if I close a query I have all its bookmarks invalid.
In your code - if Bookmark.RefreshIteration <> FRefreshIteration you continue to condition for Bookmark.Order. And if Order is less then record count then Bookmark is valid. I think that if Bookmark.RefreshIteration <> FRefreshIteration the bookmark is invalid...
That's all...
Regards
Roman Krupicka
Re: BookmarkValid in version 6.7.13
Posted: Fri 10 May 2013 14:06
by AndreyZ
That is not right. Roughly speaking, bookmark is like a number of a particular row. So, when you close and open the same dataset, bookmarks remain valid. Moreover, you can use bookmark of one dataset for another dataset (maybe not the correct thing to do, but you can do this if you like). You can check this using any other components, for example, ADO. Here is an example:
Code: Select all
var
bm: TBookmark;
begin
ADOQuery1.SQL.Text := 'select * from table1';
ADOQuery1.Open;
bm := ADOQuery1.Bookmark;
ADOQuery2.SQL.Text := 'select * from table2';
ADOQuery2.Open;
if ADOQuery2.BookmarkValid(bm) then // bm is a valid bookmark
ADOQuery2.GotoBookmark(bm);
end;