Log On
Embarcadero Home
Watch, Follow, &
Connect with Us
QualityCentral
Communities
Articles
Blogs
Resources
Downloads
Help
Quality Central
Delphi-BCB
Midas
Install
Java Midas
Socket Server
TClientDataSet
TDataSetProvider
TDCOMConnection
TMidasConnection
TOLEEnterpriseConnection
TProvider
TRemoteServer
TSimpleObjectBroker
TSocketConnection
TWebConnection
WebMidas
XML Midas
You are not logged in.
Help
Print
Public Report
Report From:
Delphi-BCB/Midas/TDataSetProvider
[ Add a report in this area ]
Report #:
2338
Status:
Closed
ApplyUpdates fails if only fields without pfInUpdate are modified
Project:
Delphi
Build #:
6.240
Version:
7.0
Submitted By:
Gabriel Corneanu
Report Type:
Basic functionality failure
Date Reported:
9/12/2002 11:31:31 AM
Severity:
Infrequently encountered problem
Last Updated:
12/15/2006 4:02:57 AM
Platform:
95, 98, 2000, NT, XP
Internal Tracking #:
82238
Resolution:
Fixed
(Resolution Comments)
Resolved in Build:
:
7.0.8.1
Duplicate of:
None
Voting and Rating
Overall Rating:
(3 Total Ratings)
4.67 out of 5
Total Votes:
3
Description
It's common to have a result set from a join where I let the provider apply updates for the fields in the main table and make the changes myself for the joined table.
The fields from the joined table have provider flags set to [] because they must not be updated by the provider.
But what happens when only fields from the joined table are changed? The provider will try to apply changes even there is no modified field.
I tracked it down and it's an error in TSQLResolver.GenUpdateSQL method. It should just check to see if there are any fields added to the SQL statement.
Steps to Reproduce:
Open project attached
Run
Change Category field //which has pfnUpdate set To False
Click applyUpdates button
//error message//
In this case the resolver should simply do nothing instead of generating an invalid update SQL statement.
Workarounds
PROVIDER.PAS
(**) (* Delphi 6.0 - 7.0 *)
(* QC#2338 fix. Mods also reqd to TSQLResolver.GenUpdateSQL
Incorrect SQL being generated when there are no fields requiring update *)
(* Dave Rowntree 05/29/03 *)
procedure TSQLResolver.InternalDoUpdate(Tree: TUpdateTree; UpdateKind: TUpdateKind);
var
Alias: string;
begin
if not IProviderSupport(Tree.Source).PSUpdateRecord(UpdateKind, Tree.Delta) then
begin
if (PSQLInfo(Tree.Data)^.QuotedTable = '') and not Tree.IsNested then
DatabaseError(SNoTableName);
if PSQLInfo(Tree.Data)^.HasObjects then Alias := DefAlias else Alias := '';
FSQL.Clear;
FParams.Clear;
case UpdateKind of
ukModify: GenUpdateSQL(Tree, FSQL, FParams, Alias);
ukInsert: GenInsertSQL(Tree, FSQL, FParams);
ukDelete: GenDeleteSQL(Tree, FSQL, FParams, Alias);
end;
if FSQL.Text <> '' then (* add this line *)
DoExecSQL(FSQL, FParams);
end;
end;
(**) (* Delphi 6.0 - 7.0 *)
(* QC#2338 fix. mods also reqd to TSQLResolver.InternalDoUpdate.
Incorrect SQL being generated when there are no fields requiring update *)
(* Dave Rowntree 05/29/03 *)
procedure TSQLResolver.GenUpdateSQL(Tree: TUpdateTree; SQL: TStrings;
Params: TParams; Alias: string);
{procedure AddField(Field: TField; InObject, InArray: Boolean);} (* rem out this line *)
function AddField(Field: TField; InObject, InArray: Boolean): boolean; (* add this line *)
var
i: Integer;
TempStr: string;
Value: Variant;
NoParam: Boolean;
begin
Result := False; (* add this line *)
NoParam := False;
with PSQLInfo(Tree.Data)^ do
begin
if Field.DataType = ftADT then
begin
if InArray then
SQL.Add(Format(' %s(',[TObjectField(Field).ObjectType]));
for i := 0 to TObjectField(Field).FieldCount - 1 do
Result := Result or (* add this line *)
AddField(TObjectField(Field).Fields[i], True, InArray);
if InArray then
begin
TempStr := SQL[SQL.Count-1];
SQL[SQL.Count-1] := Copy(TempStr, 1, Length(TempStr) - 1);
SQL.Add('),');
end;
end
else if Field.DataType = ftArray then
begin
SQL.Add(Format('%s = %s(',[Field.FullName, TObjectField(Field).ObjectType]));
for i := 0 to TObjectField(Field).FieldCount - 1 do
Result := Result or (* add this line *)
AddField(TObjectField(Field).Fields[i], InObject, True);
TempStr := SQL[SQL.Count-1];
SQL[SQL.Count-1] := Copy(TempStr, 1, Length(TempStr) - 1);
SQL.Add('),');
end
else if InArray then
begin
SQL.Add(' ?,');
Value := Field.NewValue;
if VarIsClear(Value) then Value := Field.OldValue;
TParam(Params.Add).AssignFieldValue(Field, Value);
Result := True; (* add this line *)
end
else if UseFieldInUpdate(Field) then
begin
Result := True; (* add this line *)
if (Field.DataType = ftOraClob) and (not InformixLob) then
begin
NoParam := True;
......................................
var
I, J: integer;
TempStr: string;
OraLobs: Integer;
Value: Variant;
UpdateReqd: boolean; (* add this line*)
begin
OraLobs := 0;
UpdateReqd := False; (* add this line*)
with PSQLInfo(Tree.Data)^ do
begin
if Tree.IsNested then
begin
Alias := NestAlias;
SQL.Add(Format('update the (select %s FROM %s %s',[QuoteFullName(Tree.Name, QuoteChar), { Do not
localize }
PSQLInfo(Tree.Parent.Data).QuotedTable, DefAlias]));
GenWhereSQL(Tree.Parent, SQL, Params, upWhereKeyOnly, DefAlias);
SQL.Add(Format(') %s set',[Alias])); { Do not
localize }
end else
SQL.Add(Format('update %s %s set', [QuotedTable, Alias])); { Do not
localize }
for I := 0 to Tree.Delta.FieldCount - 1 do
begin
if (Tree.Delta.Fields[i].DataType in [ftOraClob, ftOraBlob]) and
UseFieldInUpdate(Tree.Delta.Fields[I]) then
if (not InformixLob) then
Inc(OraLobs);
{AddField(Tree.Delta.Fields[i], Alias = NestAlias, False);} (* rem out this line *)
UpdateReqd := (* add this line *)
AddField(Tree.Delta.Fields[i], Alias = NestAlias, False) or (* add this line *)
UpdateReqd; (* add this line *)
end;
if not UpdateReqd then (* add this line *)
begin (* add this line *)
SQL.Clear; (* add this line *)
Exit; (* add this line *)
end; (* add this line *)
{ Remove last ',' }
TempStr := SQL[SQL.Count-1];
---------
PROVIDER.PAS
(**) (* Delphi 6.0 - 7.0 *)
(* QC#2338 fix. Mods also reqd to TSQLResolver.GenUpdateSQL
Incorrect SQL being generated when there are no fields requiring update *)
(* Dave Rowntree 05/29/03 *)
procedure TSQLResolver.InternalDoUpdate(Tree: TUpdateTree; UpdateKind: TUpdateKind);
var
Alias: string;
begin
if not IProviderSupport(Tree.Source).PSUpdateRecord(UpdateKind, Tree.Delta) then
begin
if (PSQLInfo(Tree.Data)^.QuotedTable = '') and not Tree.IsNested then
DatabaseError(SNoTableName);
if PSQLInfo(Tree.Data)^.HasObjects then Alias := DefAlias else Alias := '';
FSQL.Clear;
FParams.Clear;
case UpdateKind of
ukModify: GenUpdateSQL(Tree, FSQL, FParams, Alias);
ukInsert: GenInsertSQL(Tree, FSQL, FParams);
ukDelete: GenDeleteSQL(Tree, FSQL, FParams, Alias);
end;
if FSQL.Text <> '' then (* add this line *)
DoExecSQL(FSQL, FParams);
end;
end;
(**) (* Delphi 6.0 - 7.0 *)
(* QC#2338 fix. mods also reqd to TSQLResolver.InternalDoUpdate.
Incorrect SQL being generated when there are no fields requiring update *)
(* Dave Rowntree 05/29/03 *)
procedure TSQLResolver.GenUpdateSQL(Tree: TUpdateTree; SQL: TStrings;
Params: TParams; Alias: string);
{procedure AddField(Field: TField; InObject, InArray: Boolean);} (* rem out this line *)
function AddField(Field: TField; InObject, InArray: Boolean): boolean; (* add this line *)
var
i: Integer;
TempStr: string;
Value: Variant;
NoParam: Boolean;
begin
Result := False; (* add this line *)
NoParam := False;
with PSQLInfo(Tree.Data)^ do
begin
if Field.DataType = ftADT then
begin
if InArray then
SQL.Add(Format(' %s(',[TObjectField(Field).ObjectType]));
for i := 0 to TObjectField(Field).FieldCount - 1 do
Result := Result or (* add this line *)
AddField(TObjectField(Field).Fields[i], True, InArray);
if InArray then
begin
TempStr := SQL[SQL.Count-1];
SQL[SQL.Count-1] := Copy(TempStr, 1, Length(TempStr) - 1);
SQL.Add('),');
end;
end
else if Field.DataType = ftArray then
begin
SQL.Add(Format('%s = %s(',[Field.FullName, TObjectField(Field).ObjectType]));
for i := 0 to TObjectField(Field).FieldCount - 1 do
Result := Result or (* add this line *)
AddField(TObjectField(Field).Fields[i], InObject, True);
TempStr := SQL[SQL.Count-1];
SQL[SQL.Count-1] := Copy(TempStr, 1, Length(TempStr) - 1);
SQL.Add('),');
end
else if InArray then
begin
SQL.Add(' ?,');
Value := Field.NewValue;
if VarIsClear(Value) then Value := Field.OldValue;
TParam(Params.Add).AssignFieldValue(Field, Value);
Result := True; (* add this line *)
end
else if UseFieldInUpdate(Field) then
begin
Result := True; (* add this line *)
if (Field.DataType = ftOraClob) and (not InformixLob) then
begin
NoParam := True;
......................................
var
I, J: integer;
TempStr: string;
OraLobs: Integer;
Value: Variant;
UpdateReqd: boolean; (* add this line*)
begin
OraLobs := 0;
UpdateReqd := False; (* add this line*)
with PSQLInfo(Tree.Data)^ do
begin
if Tree.IsNested then
begin
Alias := NestAlias;
SQL.Add(Format('update the (select %s FROM %s %s',[QuoteFullName(Tree.Name, QuoteChar), { Do not
localize }
PSQLInfo(Tree.Parent.Data).QuotedTable, DefAlias]));
GenWhereSQL(Tree.Parent, SQL, Params, upWhereKeyOnly, DefAlias);
SQL.Add(Format(') %s set',[Alias])); { Do not
localize }
end else
SQL.Add(Format('update %s %s set', [QuotedTable, Alias])); { Do not
localize }
for I := 0 to Tree.Delta.FieldCount - 1 do
begin
if (Tree.Delta.Fields[i].DataType in [ftOraClob, ftOraBlob]) and
UseFieldInUpdate(Tree.Delta.Fields[I]) then
if (not InformixLob) then
Inc(OraLobs);
{AddField(Tree.Delta.Fields[i], Alias = NestAlias, False);} (* rem out this line *)
UpdateReqd := (* add this line *)
AddField(Tree.Delta.Fields[i], Alias = NestAlias, False) or (* add this line *)
UpdateReqd; (* add this line *)
end;
if not UpdateReqd then (* add this line *)
begin (* add this line *)
SQL.Clear; (* add this line *)
Exit; (* add this line *)
end; (* add this line *)
{ Remove last ',' }
TempStr := SQL[SQL.Count-1];
Attachment
Project.zip
Comments
Dave Rowntree at 9/13/2002 9:20:20 AM
-
This is a known problem. MIDAS generates invalid SQL if the only fields updated all have pfInUpdate set to False.
I changed the report Area to TDataSetProvider.
Gabriel Corneanu at 9/13/2002 10:31:26 PM
-
Of course another workaround (what I am using right now) is to check updated fields in BeforeUpdateRecord and set Applied to true if necessary. But it seems too much.
View Your Reports
Search
Server Response from: CODE1
Developer Tools
Blackfish SQL
C++Builder
Delphi
Delphi for PHP
Delphi Prism
InterBase
JBuilder
J Optimizer
3rdRail & TurboRuby
Database Tools
Change Manager
DBArtisan
DB Optimizer
ER/Studio
Performance Center
Rapid SQL
Technical Articles
Tutorials
White Papers
Press Releases
Newsletters
Add Content (GetPublished)
Audio
Audio & Video
Video
Bugs & Suggestions (QualityCentral)
Discussion Forums
Examples (CodeCentral)
Tags
Technology Partners
Downloads
Free Trials
Registered User Downloads
Beta Programs
Add Content (GetPublished)
Articles
Blogs
Bugs & Suggestions (QualityCentral)
Chats
Discussion Forums
Examples (CodeCentral)
Member Services
About
Connect with Us