Как поймать SQL, сгенерированный Delphi TDataSetProvider? - PullRequest
0 голосов
/ 25 октября 2019

У меня есть цепочка TClientDataSet, TDataSetProvider и TIBQuery, и при выполнении CDS возникает ошибка «неподготовленный оператор». Пост, по-видимому, является ошибочным сгенерированным TDataSetProvider сгенерированным обновлением. Как отловить это обновление SQL? SQL Montioring не работает для моих компонентов IBX. Я пытался использовать код (вдохновленный TClientDataset.ApplyUpdates не удается с «SQL не поддерживается» при использовании компонентов SQLDirect ):

procedure TSQLResolver.DoExecSQL(SQL: TWideStringList; Params: TParams);
var
  RowsAffected: Integer;
  TmpList: TStringList;
begin
  TmpList:=TStringList.Create;
  TmpList.LoadFromFile('C:\Test\test.txt');
  RowsAffected := (Provider.DataSet as IProviderSupport).PSExecuteStatement(SQL.Text, Params);
  if not (poAllowMultiRecordUpdates in Provider.Options) and (RowsAffected > 1) then
  begin
    TmpList.Add(SQL.Text);
    TmpList.SaveToFile('C:\Test\test.txt');
    TmpList.Free;
    (Provider.DataSet as IProviderSupport).PSEndTransaction(False);
    Provider.TransactionStarted := False;
    DatabaseError(STooManyRecordsModified);
  end;
  if RowsAffected < 1 then
    DatabaseError(SRecordChanged);
end;

Но ничего не написано в Test / test. текстовый файл. Где я могу разместить такой код регистрации?

Delphi 2010, но я думаю, что это применимо к любой версии Delphi.

1 Ответ

1 голос
/ 25 октября 2019

Причина, по которой ничего не записывается в ваш файл журнала, заключается в том, что, как вы добавили свою запись в журнал, она будет выполняться только в том случае, если обновление затрагивает более одной строки. Имо, ваш код должен быть

procedure TSQLResolver.DoExecSQL(SQL: TStringList; Params: TParams);
var
  RowsAffected: Integer;
  TmpList: TStringList;
begin
  TmpList:=TStringList.Create;
  try
    TmpList.LoadFromFile('C:\Test\test.txt');
    RowsAffected := (Provider.DataSet as IProviderSupport).PSExecuteStatement(SQL.Text, Params);
    TmpList.Add(SQL.Text);
    TmpList.SaveToFile('C:\Test\test.txt');
    if not (poAllowMultiRecordUpdates in Provider.Options) and (RowsAffected > 1) then
    begin
      (Provider.DataSet as IProviderSupport).PSEndTransaction(False);
      Provider.TransactionStarted := False;
      DatabaseError(STooManyRecordsModified);
    end;
    if RowsAffected < 1 then
      DatabaseError(SRecordChanged);
  finally
    TmpList.Free;
  end;
end;

, который должен работать независимо от количества обновленных строк. Это также исправляет утечку TmpList, которую вы настроили, освобождая TmpList в коде, который выполняется только условно. Кстати, как написано, вы обнаружите, что этот код не регистрирует значения, введенные значениями в Params, но достаточно легко добавить их в журнал или даже объединить их в зарегистрированный SQL.Text.

Надеюсь, это должно решить вашу непосредственную проблему, но, честно говоря, вам лучше потратить время на то, чтобы свести ваш код к mre . Я говорю, что по нескольким причинам, во-первых, у меня никогда не было ошибки «неподготовленный оператор» при использовании IBX + DSP / CDS, во-вторых, регистрация с использованием компонентов IBX обычно работает нормально, и в-третьих, что подготовка mre часто выявляет причину проблемы. Поэтому я подозреваю, что в коде вы не показывали нам ошибку.

Если вы настроили mre для работы с одной из примеров баз данных IB и опубликуете ее здесь как новый q (не как редактирование этой, пожалуйста), у вас гораздо больше шансов найти читателейготовы попробовать сами.

...