使用SQLDirect组件时,TClientDataset.ApplyUpdates失败,并显示“不支持SQL" [英] TClientDataset.ApplyUpdates fails with 'SQL not supported' when using SQLDirect components

查看:73
本文介绍了使用SQLDirect组件时,TClientDataset.ApplyUpdates失败,并显示“不支持SQL"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从DelphiXE2更新到Delphi Seattle 10 Update 1后,当使用

After updating from DelphiXE2 to Delphi Seattle 10 Update 1 we have issues executing TClientDataSet ApplyUpdates calls when using the SQLDirect components version 6.4.5

我做了一个小型测试应用程序.
组件: TDBGrid->TDataSource->TClientDataSet->TDataSetProvider->TSDQuery->TSDDatabase
查询是 select * from tt_plan_task ,提供程序具有 UpdateMode = upWhereAll ,ClientDataset具有 IndexFieldName = tt_plan_task_id .
我们为 tt_plan_task.tt_prj 字段修改一个值.

I made a small test app.
Components: TDBGrid -> TDataSource -> TClientDataSet -> TDataSetProvider -> TSDQuery -> TSDDatabase
Query is select * from tt_plan_task, Provider has UpdateMode=upWhereAll, ClientDataset has IndexFieldName=tt_plan_task_id.
We modify one value for field tt_plan_task.tt_prj.

在执行 ApplyUpdates(0)时,该代码会跟踪到 DataSnap.Provider 中的 TSQLResolver.InternalDoUpdate (对于 UpdateKind = ukModify).
在那里,生成的SQL和参数看起来像预期的那样.
然后,代码跳至

When executing ApplyUpdates(0), the code traces into TSQLResolver.InternalDoUpdate in DataSnap.Provider (for UpdateKind=ukModify).
There, the generated SQL and parameters look as expected.
The code then jumps to

procedure TSQLResolver.DoExecSQL(SQL: TStringList; Params: TParams);
var
  RowsAffected: Integer;
begin
  RowsAffected := (Provider.DataSet as IProviderSupportNG).PSExecuteStatement(SQL.Text, Params);

此语句崩溃,错误为不支持SQL (Data.DBConsts中为SProviderSQLNotSupported)

This statement crashes with error SQL not supported (SProviderSQLNotSupported in Data.DBConsts)

但是由于这是一个接口,我无法进一步跟踪.
我不知道如何从这里着手解决问题.任何建议,怎么做或可能会发生什么?

But since this an interface, I cannot trace further.
I don't know how to proceed from here in resolving the issue. Any suggestions how to, or what could be going on?

其他信息:

  • 通过TSDQuery组件执行SELECT和(参数化的)UPDATE查询工作正常.
  • 使用具有所有FireDac组件( TDBGrid-> TDataSource-> TClientDataSet-> TDataSetProvider-> TFDQuery-> TDFConnection )的clientdataset可以正常工作
  • 这是具有数据库方言3的FireBird数据库
  • FireBird版本为2.5.3.26778
  • Delphi 10安装时没有Interbase组件
  • 所有这些都在Win7 VM中,在其中删除了Delphi XE2(清除了所有的"Borland/CodeGear/Embarcadero"),并安装了Seattle.我的同事在干净的Win10 VM中进行干净的Seattle安装时也遇到类似的问题.
  • 应用程序和FireBird是Win32,操作系统是Win64
  • Executing SELECT and (parameterized) UPDATE queries through a TSDQuery component work fine.
  • Using a clientdataset with all FireDac components (TDBGrid -> TDataSource -> TClientDataSet -> TDataSetProvider -> TFDQuery -> TDFConnection) (different testapp) works fine
  • This is a FireBird database with database dialect 3
  • FireBird version is 2.5.3.26778
  • Delphi 10 was installed without the Interbase components
  • This is all in a Win7 VM where Delphi XE2 was removed from (everything 'Borland/CodeGear/Embarcadero' cleaned out), and Seattle installed. My colleague has similar issues with a clean Seattle installation in a clean Win10 VM.
  • Apps and FireBird are Win32, OSes are Win64

[注意:请自行回答此问题,因为我花了相当长的时间才能弄清楚这一点.可能会对别人有帮助.]

推荐答案

Delphi XE3在DOA上> SProviderSQLNotSupported ,其中用户在使用Oracle Direct Access时也遇到类似的问题.
建议:

When Googling the error message I stumbled upon this post SProviderSQLNotSupported on DOA with Delphi XE3 where a user had similar issues with Oracle Direct Access.
It suggests either:

1)以性能为代价设置 TDataSetProvider.ResolveToDataSet = true .在测试应用中有效.

1) Set TDataSetProvider.ResolveToDataSet=true at the cost of performance. This works in the test app.

2) PSExecuteStatement 可能未在第三方软件中实现(覆盖),其基本过程来自 data.db :

2) The PSExecuteStatement may not be implemented (overridden) in the 3rd party software, and its base procedure from data.db kicks in:

function TDataSet.PSExecuteStatement(const ASQL: string; AParams: TParams): Integer;
begin
  Result := 0;
  DatabaseError(SProviderSQLNotSupported, Self);
end;

第二种情况是发生了什么.SQLDirect代码确实具有对TSDDataSet方法的覆盖

That second situation is what happens. The SQLDirect code does have an override for the TSDDataSet method

function PSExecuteStatement(const ASQL: string; AParams: TParams; {$IFDEF SD_CLR} var ResultSet: TObject {$ELSE} {$IFDEF SD_VCL17} var ResultSet: TDataSet {$ELSE} ResultSet: TSDPtr = nil {$ENDIF} {$ENDIF}): Integer; overload; override;

在Delphi Seattle下,该文件解析/编译以覆盖:

which under Delphi Seattle resolves/compiles to override:

function PSExecuteStatement(const ASQL: string; AParams: TParams; var ResultSet: TDataSet): Integer; overload; override;

但没有

function TDataSet.PSExecuteStatement(const ASQL: string; AParams: TParams): Integer;

解决方案是添加一个:

在SDEngine.pas中TSDDateSet的受保护方法中,更新如下:

In the protected methods for TSDDateSet in SDEngine.pas, update as follows:

function PSExecuteStatement(const ASQL: string; AParams: TParams): Integer; overload; override; // New override
function PSExecuteStatement(const ASQL: string; AParams: TParams; {$IFDEF SD_CLR} var ResultSet: TObject {$ELSE} {$IFDEF SD_VCL17} var ResultSet: TDataSet {$ELSE} ResultSet: TSDPtr = nil {$ENDIF} {$ENDIF}): Integer; overload; override;

具有实现:

function TSDDataSet.PSExecuteStatement(const ASQL: string; AParams: TParams): Integer;  // JD 20-4-2016
var
  ds: TDataSet;
begin
  ds := nil;
  Result := InternalPSExecuteStatement( ASQL, AParams, false, ds );
end;

这篇关于使用SQLDirect组件时,TClientDataset.ApplyUpdates失败,并显示“不支持SQL"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆