пропадает значение параметра после Conditions.Add

Обсуждение возникших проблем, предложений и ошибок UniDAC компонентов
Закрыто
Akella
Сообщения: 217
Зарегистрирован: Пн 02 апр 2012 14:41

пропадает значение параметра после Conditions.Add

Сообщение Akella » Чт 27 фев 2020 14:29

Delphi Tokyo, UniDAC 8.0.1.
В UniQuery добавлено 2 условия и 2 параметра. Потом нужно закрыть датасет, добавить ещё одно условие (без параметров) и снова открыть. Проблема в том, что сразу после добавления нового условия, т.е. после "UniQuery1.Conditions.Add" пропадает значение одного параметров, при этом имена параметров/условий не пересекаются (т.е. разные).

сделал такой пример.

Код: Выделить всё

procedure SetCondVal(uniQuery: TuniQuery; const Name, Val: string);
Var
  Cond: TDACondition;
  q: integer;
  n, v: string;
begin
  Cond := uniQuery.Conditions.Find(Name);
  
// здесь значение параметра (LCDMIN) ещё на месте
  for q := 0 to pred(uniQuery.ParamCount) do
  begin
    n := uniQuery.Params[q].Name;
    v := uniQuery.Params[q].AsString;
    v := v;// для бряки
  end;

  if Assigned(Cond) then
  begin
    Cond.Value := Val;
    Cond.Enable;
  end
  else
    uniQuery.Conditions.Add(Name, Val, True);// это условие выполняется

// здесь значение параметра (LCDMIN) уже потерялось
  for q := 0 to pred(uniQuery.ParamCount) do
  begin
    n := uniQuery.Params[q].Name;
    v := uniQuery.Params[q].AsString;
    v := v;// для бряки
  end;
end;
вот 4 снимка, на них видна хронология
http://prntscr.com/r8hrbx
http://prntscr.com/r8hs9s

http://prntscr.com/r8hskj
http://prntscr.com/r8hstg

Может это поможет решить проблему.
Параметр "TYPESIDS" добавлен с помощью макроса, а проблемный параметр "LCDMIN" добавлен с помощью Conditions.Add().

Я не выполняю ни Conditions.Disable, ни Conditions.Clear, просто сразу добавляю новое условие.
По идее, параметр не должен терять свое значение. Сам параметр же не теряется.

ViktorV
Devart Team
Сообщения: 212
Зарегистрирован: Чт 31 июл 2014 09:52

Re: пропадает значение параметра после Conditions.Add

Сообщение ViktorV » Пт 28 фев 2020 12:54

Для более быстрого и полного ответа, пожалуйста, составьте и вышлите нам, с помощью контактной формы https://www.devart.com/company/contactform.html, небольшой пример демонстрирующий указаное вами поведение, включающий необходимые скрапты на создание объектов БдД и укажите точную версию вашего MySQL сервера.

Akella
Сообщения: 217
Зарегистрирован: Пн 02 апр 2012 14:41

Re: пропадает значение параметра после Conditions.Add

Сообщение Akella » Сб 29 фев 2020 08:54

Пока создавал тестовый проект, появилась ещё одна проблема после того, как я заменил текст макроса.
И эта ошибка происходит, если включено свойство SmartFetch.
Project raised exception class EIBCError with message 'Dynamic SQL Error
SQL error code = -204
Ambiguous field name between table TYPES and table TABLE1
ID'.

Код: Выделить всё

procedure TForm1.Button1Click(Sender: TObject);
Var
 i: integer;
begin
  UniConnection1.Connect;

  UniQuery1.close;
  UniQuery1.Conditions.Clear;

  UniQuery1.MacroByName('TYPES').Value := 'LEFT JOIN TYPES T ON T.ID = A.ID_TYPE AND T.USERNAME = :USERNAME';
  UniQuery1.ParamByName('USERNAME').AsString := 'user';


  UniQuery1.open;<<< ошибка при открытии


  UniQuery1.close;

  UniQuery1.Conditions.Add('tname', 'T.NAME = :TNAME', True);
  UniQuery1.Conditions.Enable;
  UniQuery1.ParamByName('TNAME').AsString := 'qqqq';

  UniQuery1.Conditions.Add('tname', 'T.ID > 10', True);
  Memo1.Lines.Add(UniQuery1.FinalSQL);
  UniQuery1.open;

  Memo1.Lines.Add(UniQuery1.FinalSQL);


  Memo1.Lines.Add('');
  Memo1.Lines.Add('params');
  for I := 0 to pred(UniQuery1.Params.Count) do
    Memo1.Lines.Add(UniQuery1.Params[i].Name + ' = ' + UniQuery1.Params[i].AsString);

end;
Тестовый проект я отправлю со страницы ContactForm.

Я забыл добавить, что база для Firebird 3 (UTF8).

Запрос, который выдает FinalSQL, вполне нормальный и в IBExpert ID он выполняется без ошибок

Код: Выделить всё

SELECT
  A.ID,
  A.NAME NAME_USER,
  A.REMARK

  FROM TABLE1 A
  LEFT JOIN TYPES T ON T.ID = A.ID_TYPE AND T.USERNAME = :USERNAME

Akella
Сообщения: 217
Зарегистрирован: Пн 02 апр 2012 14:41

Re: пропадает значение параметра после Conditions.Add

Сообщение Akella » Сб 29 фев 2020 16:44

Пример для первого вопрос отправил и вот картинка
http://prntscr.com/r9ijfk
где видно, что второй параметр пуст.

ViktorV
Devart Team
Сообщения: 212
Зарегистрирован: Чт 31 июл 2014 09:52

Re: пропадает значение параметра после Conditions.Add

Сообщение ViktorV » Пн 02 мар 2020 14:58

Akella писал(а): Сб 29 фев 2020 08:54 Пока создавал тестовый проект, появилась ещё одна проблема после того, как я заменил текст макроса.
И эта ошибка происходит, если включено свойство SmartFetch.
Project raised exception class EIBCError with message 'Dynamic SQL Error
SQL error code = -204
Ambiguous field name between table TYPES and table TABLE1
ID'.

Код: Выделить всё

procedure TForm1.Button1Click(Sender: TObject);
Var
 i: integer;
begin
  UniConnection1.Connect;

  UniQuery1.close;
  UniQuery1.Conditions.Clear;

  UniQuery1.MacroByName('TYPES').Value := 'LEFT JOIN TYPES T ON T.ID = A.ID_TYPE AND T.USERNAME = :USERNAME';
  UniQuery1.ParamByName('USERNAME').AsString := 'user';


  UniQuery1.open;<<< ошибка при открытии


  UniQuery1.close;

  UniQuery1.Conditions.Add('tname', 'T.NAME = :TNAME', True);
  UniQuery1.Conditions.Enable;
  UniQuery1.ParamByName('TNAME').AsString := 'qqqq';

  UniQuery1.Conditions.Add('tname', 'T.ID > 10', True);
  Memo1.Lines.Add(UniQuery1.FinalSQL);
  UniQuery1.open;

  Memo1.Lines.Add(UniQuery1.FinalSQL);


  Memo1.Lines.Add('');
  Memo1.Lines.Add('params');
  for I := 0 to pred(UniQuery1.Params.Count) do
    Memo1.Lines.Add(UniQuery1.Params[i].Name + ' = ' + UniQuery1.Params[i].AsString);

end;
Тестовый проект я отправлю со страницы ContactForm.

Я забыл добавить, что база для Firebird 3 (UTF8).

Запрос, который выдает FinalSQL, вполне нормальный и в IBExpert ID он выполняется без ошибок

Код: Выделить всё

SELECT
  A.ID,
  A.NAME NAME_USER,
  A.REMARK

  FROM TABLE1 A
  LEFT JOIN TYPES T ON T.ID = A.ID_TYPE AND T.USERNAME = :USERNAME
При открытии таблицы в режиме SmartFetch, считываются только значения ключевых полей и полей указанных в свойстве PrefetchedFields для всех записей, возвращаемых запросом. После открытия таблицы, происходит чтение полей для количества строк, указанных в свойстве FetchRows. Остальные поля будут прочтены непосредственно при обращении к ним.
Эффективность работы SmartFetch при извлечении любых данных таблицы зависит от используемых в этой таблице типов полей.
Наибольший прирост производительности наблюдается при использовании SmartFetch для типов данных с большими значениями, таких как long string, BLOB, и т.д.
При использовании SmartFetch режима UniDAC, если свойство TUniQuery.SmartFetch.SQLGetKeyValues установлено в пустую строку, UniDAC пытается составить и выполнить запрос на чтение ключевых полей и полей указанных в свойстве PrefetchedFields.
Когда SQL запрос является сложным, как в вашем случае, автоматически сгенерированный запрос может быть некорректным. В таком случае вам следует в свойстве TUniQuery.SmartFetch.SQLGetKeyValues.Text указать запрос на получения полей, которые будут уникально идентифицировать запись. Например:

Код: Выделить всё

SELECT
  A.ID
  FROM TABLE1 A
  LEFT JOIN TYPES T ON T.ID = A.ID_TYPE AND T.USERNAME = :USERNAME

ViktorV
Devart Team
Сообщения: 212
Зарегистрирован: Чт 31 июл 2014 09:52

Re: пропадает значение параметра после Conditions.Add

Сообщение ViktorV » Вт 03 мар 2020 15:39

Akella писал(а): Чт 27 фев 2020 14:29 Delphi Tokyo, UniDAC 8.0.1.
В UniQuery добавлено 2 условия и 2 параметра. Потом нужно закрыть датасет, добавить ещё одно условие (без параметров) и снова открыть. Проблема в том, что сразу после добавления нового условия, т.е. после "UniQuery1.Conditions.Add" пропадает значение одного параметров, при этом имена параметров/условий не пересекаются (т.е. разные).

сделал такой пример.

Код: Выделить всё

procedure SetCondVal(uniQuery: TuniQuery; const Name, Val: string);
Var
  Cond: TDACondition;
  q: integer;
  n, v: string;
begin
  Cond := uniQuery.Conditions.Find(Name);
  
// здесь значение параметра (LCDMIN) ещё на месте
  for q := 0 to pred(uniQuery.ParamCount) do
  begin
    n := uniQuery.Params[q].Name;
    v := uniQuery.Params[q].AsString;
    v := v;// для бряки
  end;

  if Assigned(Cond) then
  begin
    Cond.Value := Val;
    Cond.Enable;
  end
  else
    uniQuery.Conditions.Add(Name, Val, True);// это условие выполняется

// здесь значение параметра (LCDMIN) уже потерялось
  for q := 0 to pred(uniQuery.ParamCount) do
  begin
    n := uniQuery.Params[q].Name;
    v := uniQuery.Params[q].AsString;
    v := v;// для бряки
  end;
end;
вот 4 снимка, на них видна хронология
http://prntscr.com/r8hrbx
http://prntscr.com/r8hs9s

http://prntscr.com/r8hskj
http://prntscr.com/r8hstg

Может это поможет решить проблему.
Параметр "TYPESIDS" добавлен с помощью макроса, а проблемный параметр "LCDMIN" добавлен с помощью Conditions.Add().

Я не выполняю ни Conditions.Disable, ни Conditions.Clear, просто сразу добавляю новое условие.
По идее, параметр не должен терять свое значение. Сам параметр же не теряется.
Спасибо за информацию мы воcпроизвели проблему со сбросом значения параметра, используемого в TDACondition при добавлении нового TDACondition, и постараемся исправить его в следующем билде. Как временное решение вы можете использовать следующие рекомендации:
- добавить все TDACondition;
- вызвать метод TDAConditions.Enable для возможности установить значения параметров используемых в TDACondition;
- установить значения для всех параметров;
- вызвать метод TUniQuery.Open.

Закрыто