Error when I try to edit and save data without modification

The alpha/beta tester's forum for ZeosLib 7.0.x series

Report problems concerning our Delphi 2009+ version and new Zeoslib 7.0 features here.

This is a forum that will be removed once the 7.X version goes into stable!!

Moderators: gto, EgonHugeist, olehs

silvioprog
Junior Boarder
Junior Boarder
Posts: 42
Joined: 10.01.2009, 00:34
Location: Brasil
Contact:

Post by silvioprog »

Finally, after 3 more weeks...
No problems. :)
Can you dig deeper into the UncachedGetColumns procedure?
Yes... hmm, but how to I make this?
dopidaniel
Fresh Boarder
Fresh Boarder
Posts: 7
Joined: 12.09.2009, 16:37

Post by dopidaniel »

Hi Mark

I had the same problems reported by Silvio,

I applied the modification below, which appears to have prevented the error happens. But I'm not really sure if this is the best approach, or whether this will cause side effects in other routines ...

What do you think?

Code: Select all

procedure TZInterbase6PreparedStatement.Prepare;
begin
  if SQL = '' then    // <----- I inserted this verification
     exit;

  LogPrepStmtMessage(lcPrepStmt, SQL);
  StmtHandle := nil;
  with FIBConnection do
  begin
    StatementType := ZDbcInterbase6Utils.PrepareStatement(GetPlainDriver,
        GetDBHandle, GetTrHandle, GetDialect, SQL, StmtHandle);

    if StatementType in [stSelect, stExecProc] then
      begin
        SQLData := TZResultSQLDA.Create(GetPlainDriver, GetDBHandle, GetTrHandle);
        PrepareResultSqlData(GetPlainDriver, GetDBHandle, GetDialect,
          SQL, StmtHandle, SQLData);
      end;
  end;
  CheckInterbase6Error(SQL);
  // LogPrepStmtMessage(lcPrepStmt, SQL);
  inherited Prepare;
end;
User avatar
mdaems
Zeos Project Manager
Zeos Project Manager
Posts: 2766
Joined: 20.09.2005, 15:28
Location: Brussels, Belgium
Contact:

Post by mdaems »

This changes doesn't have side effects in the test suite.
BUT... it would be better to set a breakpoint on the exist statement an see when this code is effectively used. An emptty statement should NEVER be prepared. So why is it done?

Silvio, does this code 'fix' your code too?

Mark
Image
silvioprog
Junior Boarder
Junior Boarder
Posts: 42
Joined: 10.01.2009, 00:34
Location: Brasil
Contact:

Post by silvioprog »

Yes, it's works, this solution fixed the error definitely.

Thanks boys.
User avatar
mdaems
Zeos Project Manager
Zeos Project Manager
Posts: 2766
Joined: 20.09.2005, 15:28
Location: Brussels, Belgium
Contact:

Post by mdaems »

This changes doesn't have side effects in the test suite.
BUT... it would be better to set a breakpoint on the exist statement an see when this code is effectively used. An emptty statement should NEVER be prepared. So why is it done?
dopidaniel,

Can you find out when this exit happens in your case and why it is like that? I know the debugging isn't 'fun', but an answer on this question would make the fix more correct and clean.
Let's put it like this: coitus interuptus avoids pregnancy when done in time, but it isn't elegant and fun. So let's avoid 'Preparus interuptus' when possible.

Mark
Image
guidoaerts
Senior Boarder
Senior Boarder
Posts: 93
Joined: 01.07.2009, 16:07

Post by guidoaerts »

well, that's a nice metafor, Mark.
Guido
dopidaniel
Fresh Boarder
Fresh Boarder
Posts: 7
Joined: 12.09.2009, 16:37

Post by dopidaniel »

Hi Mark,

Sorry for the delay ... had not noticed the response of the topic

Debugging again, I thought better to insert a check in: procedure TZGenericCachedResolver.PostUpdates

Code: Select all

TZGenericCachedResolver.PostUpdates

.......
      utModified:
          begin
        SQL: = FormUpdateStatement (SQLParams, OldRowAccessor, NewRowAccessor);
            If SQL =''then    // <---- here
               exit;
            If Assigned (UpdateStatement) and (SQL <> UpdateStatement.GetSQL) then
              UpdateStatement: = nil;
            If not Assigned (UpdateStatement) then
              UpdateStatement: = CreateResolverStatement (SQL);
            Statement: = UpdateStatement;
          end;
....
So this way, an unnecessary Statement is not created
User avatar
mdaems
Zeos Project Manager
Zeos Project Manager
Posts: 2766
Joined: 20.09.2005, 15:28
Location: Brussels, Belgium
Contact:

Post by mdaems »

dopidaniel,
That's better indeed. And it explains WHEN the error is occuring. That is when PostUpdates is called and TZGenericCachedResolver.FormUpdateStatement returns an empty string because no columns have been changed.
So

Code: Select all

function TZGenericCachedResolver.FormUpdateStatement(Columns: TObjectList;
  OldRowAccessor, NewRowAccessor: TZRowAccessor): string;
var
  I: Integer;
  Current: TZResolverParameter;
  TableName: string;
  Temp: string;
begin
  TableName := DefineTableName;
  DefineUpdateColumns(Columns, OldRowAccessor, NewRowAccessor);
  if Columns.Count = 0 then
  begin
    Result := '';
    Exit;
  end;

  Temp := '';
  for I := 0 to Columns.Count - 1 do
  begin
    Current := TZResolverParameter(Columns[I]);
    if Temp <> '' then
      Temp := Temp + ',';
    Temp := Temp + IdentifierConvertor.Quote(Current.ColumnName) + '=?';
  end;

  Result := Format('UPDATE %s SET %s', [TableName, Temp]);
  DefineWhereKeyColumns(Columns);
  Result := Result + FormWhereClause(Columns, OldRowAccessor);
end;
is only executed until the DefineUpdateColumns call.
So there seem to be 2 options:
- Your escape
- Avoiding the resolver's PostUpdate method isn't called for these rows in TZAbstractCachedResultSet.PostRowUpdates

Second version may be even more efficient, but requires some study to make sure only the really unchanged records are skipped. So I commit your version for now. (SVN rev 861 in testing branch, to be merged to 6.6-patches)

Mark
Image
Locked