Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/Midas/TDataSetProvider    [ Add a report in this area ]  
Report #:  4014   Status: Closed
CDS.RefreshRecord with dbx as data access layer can fail to refresh some fields.
Project:  Delphi Build #:  6.240
Version:    7.0 Submitted By:   Dave Rowntree
Report Type:  Basic functionality failure Date Reported:  4/5/2003 2:31:53 AM
Severity:    Commonly encountered problem Last Updated: 3/20/2012 2:24:39 AM
Platform:    All versions Internal Tracking #:   159433
Resolution: Fixed (Resolution Comments) Resolved in Build: : 7.0.8.1
Duplicate of:  None
Voting and Rating
Overall Rating: (1 Total Rating)
5.00 out of 5
Total Votes: None
Description
CDS.RefreshRecord with dbx as data access layer can fail to refresh some fields.

When a unidirectional dataset is used as the DSP.DataSet, CDS.RefreshRecord causes the DSP to constructs an SQL select statement to retrieve the record of interest from the DB .

The select clause is built by TSQLResolver.GenSelectSQL using code which *only* includes fields (to be refreshed) with pfInWhere in the DSP.DataSet field ProviderFlags. So, any field that does *not* have pfInWhere in it's ProviderFlag will *not* be refreshed by CDS.RefreshRecord. I do not agree with this. A more sensible selection criteria for fields to be included in the select clause for RefreshRecord would be those fields with pfInUpdate in their DSP.DataSet ProviderFlags. The select statement MIDAS constructs is a single table select, so the CDS.ApplyUpdates rules would then also apply to CDS.RefreshRecord.

Please see QC4006 which is also a problem relating to the GenSelectSQL procedure.
Steps to Reproduce:
1. Download the test case app from Attachments.
2. Open the test case app in Delphi.
3. Follow the on screen steps.
-------------------------------------------------------------------
Workarounds
(**) (* Delphi 6.0 - 7.0 *)
(* fix to select correct fields for CDS.RefreshRecord.
   if you apply this fix you
***** MUST ALSO APPLY THE FIX FOR TSQLResolver.InitializeConflictBuffer QC4006 *****)
(* Dave Rowntree 04/04/03 *)
procedure TSQLResolver.GenSelectSQL(Tree: TUpdateTree; SQL: TStrings;
  Params: TParams; Alias: string; Mode: TUpdateMode = upWhereKeyOnly);
var
  i: Integer;
  Temp: string;
begin
  with PSQLInfo(Tree.Data)^ do
  begin
    SQL.Add('select');
    for i := 0 to Tree.Delta.FieldCount - 1 do
      with Tree.Delta.Fields[i] do
        if not (DataType in [ftDataSet, ftReference]) and (FieldKind = fkData)
           {and (pfInWhere in ProviderFlags) then} (**) (* rem out this line *)
           and (pfInUpdate in ProviderFlags) then  (**) (* add this line *)
          SQL.Add(Format(' %s%s%s%1:s,',[QuotedTableDot, QuoteChar, Origin]));
    { Remove last ',' }
    Temp := SQL[SQL.Count-1];
    SQL[SQL.Count-1] := Copy(Temp, 1, Length(Temp) - 1);
    SQL.Add(Format(' from %s %s',[QuotedTable, Alias]));     { Do not localize }
    GenWhereSQL(Tree, SQL, Params, Mode, Alias);
  end;
end;

---------

(**) (* Delphi 6.0 - 7.0 *)
(* fix to select correct fields for CDS.RefreshRecord.
   if you apply this fix you
***** MUST ALSO APPLY THE FIX FOR TSQLResolver.InitializeConflictBuffer QC4006 *****)
(* Dave Rowntree 04/04/03 *)
procedure TSQLResolver.GenSelectSQL(Tree: TUpdateTree; SQL: TStrings;
  Params: TParams; Alias: string; Mode: TUpdateMode = upWhereKeyOnly);
var
  i: Integer;
  Temp: string;
begin
  with PSQLInfo(Tree.Data)^ do
  begin
    SQL.Add('select');
    for i := 0 to Tree.Delta.FieldCount - 1 do
      with Tree.Delta.Fields[i] do
        if not (DataType in [ftDataSet, ftReference]) and (FieldKind = fkData)
           {and (pfInWhere in ProviderFlags) then} (**) (* rem out this line *)
           and (pfInUpdate in ProviderFlags) then  (**) (* add this line *)
          SQL.Add(Format(' %s%s%s%1:s,',[QuotedTableDot, QuoteChar, Origin]));
    { Remove last ',' }
    Temp := SQL[SQL.Count-1];
    SQL[SQL.Count-1] := Copy(Temp, 1, Length(Temp) - 1);
    SQL.Add(Format(' from %s %s',[QuotedTable, Alias]));     { Do not localize }
    GenWhereSQL(Tree, SQL, Params, Mode, Alias);
  end;
end;
Attachment
4014.zip
Comments

wayne hubbard at 6/10/2003 7:06:02 AM -

Although I agree that it's more sensible using pfInUpdate vs. pfInWhere,
I wonder why RefreshRecord shouldn't just work the same as CDS.Refresh,
and retrieve all fields, albeit for just one record?

Dave Rowntree at 6/14/2003 3:56:35 AM -
The MIDAS CDS.RefreshRecord method needs to obtain current field values from the DB in order to update the CDS fields.

Since D6 the MIDAS CDS.RefreshRecord method distinguishes between unidirectional and bidirectional cursors for the DSP.DataSet. If a unidirectional DS is used (e.g. dbexpress), MIDAS constructs an SQL select statement to retrieve just the appropriate record from the DB. The SQL statement generated is a simple, single table select statement. This same single table restriction applies to CDS.ApplyUpdates. Since the original DSP.DataSet select (that was run to obtain the original data when the CDS was opened) may have invloved more than one table, it can not be assumed that all the fields in the CDS are from the same DB table. It is necessary that MIDAS only include fields from a single table in it's SQL select statement. Using the pfInUpdate ProviderFlags to determine which fields to include is applying the same rules as for the CDS.ApplyUpdates.

Server Response from: ETNACODE01