Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Firebird, InterBase Новый топик    Ответить
 Добавление информации в StatusVector  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11911
Хочу расширить информацию в StatusVector своим сообщением.

Делаю так
procedure Test(AStatus: IStatus; AExcept: FBException);
var
  LStatus: NativeIntPtr;
  LCurStatus: NativeIntPtr;
  LNewStatus: array of NativeInt;
  LCnt: Integer;
  LLogger: ILogger;
begin
  LStatus := AExcept.getStatus.getErrors;
  LCurStatus := LStatus;
  // Вычисляем текущий размер вектора
  LCnt := 0;
  while LCurStatus^ <> isc_arg_end do begin
    Inc(LCurStatus);
    Inc(LCnt);
  end;
  // Расширяем вектор на 5 значений
  SetLength(LNewStatus, LCnt + 5);
  LCurStatus := LStatus;
  LCnt := 0;
  // Копируем значение в новый вектор
  while LCurStatus^ <> isc_arg_end do begin
    LNewStatus[LCnt] := LCurStatus^;
    Inc(LCurStatus);
    Inc(LCnt);
  end;
  // Добавляем дополнительную информацию
  LNewStatus[LCnt + 0] := isc_arg_gds;
  LNewStatus[LCnt + 1] := isc_random;
  LNewStatus[LCnt + 2] := isc_arg_string;
  LNewStatus[LCnt + 3] := NativeInt(PAnsiChar('Additional info'));
  LNewStatus[LCnt + 4] := isc_arg_end;
  AStatus.setErrors(@LNewStatus[0]);
  raise FbException.Create(AStatus);
end;
В итоге на клиенте (IBExpert) я получаю информацию только из исходного вектора. Если же я перенесу свой блок в начало, то получаю ошибку на клиенте
<Missing arg #1 - possibly status vector overflow>, column <Missing arg #2 - possibly status vector overflow>.


Или сама идея работать не будет и я могу возвращать либо стандартный вектор, либо кастомный?

С уважением, Vasilisk
15 июн 20, 19:52    [22151229]     Ответить | Цитировать Сообщить модератору
 Re: Добавление информации в StatusVector  [new]
hvlad
Member

Откуда:
Сообщений: 10954
_Vasilisk_
  // Вычисляем текущий размер вектора
  LCnt := 0;
  while LCurStatus^ <> isc_arg_end do begin
    Inc(LCurStatus);
    Inc(LCnt);
  end;
Это не совсем правильно, если где-то есть элемент с аргументами и кто-то из них равен нулю - ты неверно определишь конец вектора.
То же самое при копировании.


_Vasilisk_
В итоге на клиенте (IBExpert) я получаю информацию только из исходного вектора
isc_arg_end из первоначального вектора не остался ?

Как это вообще используется ? Зачем AStatus передан как параметр ?
15 июн 20, 20:27    [22151240]     Ответить | Цитировать Сообщить модератору
 Re: Добавление информации в StatusVector  [new]
hvlad
Member

Откуда:
Сообщений: 10954
Все isc_arg_XXX коды, кроме isc_arg_cstring и isc_arg_end имеют 1 параметр.
isc_arg_cstring имеет 2 пар-ра и isc_arg_end не имеет пар-ров.

Поэтому вот так будет лучше, если я правильно помню Pascal

  LCurStatus := LStatus;
  // Вычисляем текущий размер вектора
  LCnt := 0;
  while LCurStatus^ <> isc_arg_end do
    if (LCurStatus^ = isc_arg_cstring)
    then Inc(LCurStatus, 3);
    else Inc(LCurStatus, 2);

  LCnt := LCurStatus - LStatus;
15 июн 20, 20:46    [22151244]     Ответить | Цитировать Сообщить модератору
 Re: Добавление информации в StatusVector  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 50343

Эх, а ведь просил я IStatus::append()...

Posted via ActualForum NNTP Server 1.5

15 июн 20, 22:06    [22151266]     Ответить | Цитировать Сообщить модератору
 Re: Добавление информации в StatusVector  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11911
hvlad
Это не совсем правильно, если где-то есть элемент с аргументами и кто-то из них равен нулю - ты неверно определишь конец вектора.
Принимается. Но в данном случае такого элемента не было.
hvlad
isc_arg_end из первоначального вектора не остался ?
Нет.
hvlad
Как это вообще используется ?
Это в UDR. В функции идет цикл по записям. И если на какой-то записи произошла ошибка, хочу дополнить текст ошибки идентификатором этой записи
hvlad
Зачем AStatus передан как параметр ?
Он у меня есть. По нему поднимаю исключение
hvlad
Поэтому вот так будет лучше
Ничего не изменилось.

+ Код
procedure HandleFBExcept(AStatus: IStatus; AExcept: FbException);
var
  LLogger: ILogger;
  LStatus: NativeIntPtr;
  LCurStatus: NativeIntPtr;
  LNewStatus: array of NativeInt;
  LCnt: Integer;
begin
  LLogger := TLoggerFactory.GetLogger('Test');
  LStatus := AExcept.getStatus.getErrors;
  // Логируем текущий вектор
  ShowStatus(LLogger, LStatus);
  LCurStatus := LStatus;
  // Вычисляем длину вектора
  while LCurStatus^ <> isc_arg_end do begin
    if LCurStatus^ = isc_arg_cstring then
      Inc(LCurStatus, 3)
    else
      Inc(LCurStatus, 2);
  end;
  LCnt := (NativeInt(LCurStatus) - NativeInt(LStatus));
  // Выделяем память под новый вектор
  SetLength(LNewStatus, LCnt + 5);
  // Копируем старый вектор, в новый
  Move(LStatus^, LNewStatus[0], LCnt);
  LCnt := LCnt div SizeOf(LNewStatus[0]);
  // Добавляем новый блок
  LNewStatus[LCnt + 0] := isc_arg_gds;
  LNewStatus[LCnt + 1] := isc_random;
  LNewStatus[LCnt + 2] := isc_arg_string;
  LNewStatus[LCnt + 3] := NativeInt(PAnsiChar('Additional info'));
  LNewStatus[LCnt + 4] := isc_arg_end;
  AStatus.setErrors(@LNewStatus[0]);
  LLogger.Log('---------------');
  LStatus := AStatus.getErrors;
  // Логируем новый вектор
  ShowStatus(LLogger, LStatus);
  raise FbException.Create(AStatus);
end;

+ ShowStatus
procedure ShowStatus(const ALogger: ILogger; AVector: NativeIntPtr);
var
  LCur: NativeIntPtr;
  LDesc: string;
  LIdx: Integer;
begin
  LCur := AVector;
  LIdx := 0;
  while True do begin
    ArgCodes.TryGetValue(LCur^, LDesc);
    ALogger.Log('[%2d]: %d (%s)', [LIdx, LCur^, LDesc]);
    case LCur^ of
      isc_arg_end: Break;
      isc_arg_string: begin
        Inc(LIdx);
        Inc(LCur);
        ALogger.Log('[%2d]:   %s', [LIdx, PAnsiChar(LCur^)]);
      end;
      isc_arg_cstring: begin
        Inc(LIdx);
        Inc(LCur);
        ALogger.Log('[%2d]:   %d', [LIdx, LCur^]);
        Inc(LIdx);
        Inc(LCur);
        ALogger.Log('[%2d]:   %s', [LIdx, PAnsiChar(LCur^)]);
      end;
    else
      Inc(LIdx);
      Inc(LCur);
      GDSCodes.TryGetValue(LCur^, LDesc);
      ALogger.Log('[%2d]:   %d (%s)', [LIdx, LCur^, LDesc]);
    end;
    Inc(LIdx);
    Inc(LCur);
  end;
end;

+ Лог
[ 0]: 1 (isc_arg_gds)
[ 1]: 335544569 (isc_dsql_error)
[ 2]: 1 (isc_arg_gds)
[ 3]: 335544436 (isc_sqlerr)
[ 4]: 4 (isc_arg_number)
[ 5]: -206 ()
[ 6]: 1 (isc_arg_gds)
[ 7]: 335544578 (isc_dsql_field_err)
[ 8]: 1 (isc_arg_gds)
[ 9]: 335544382 (isc_random)
[10]: 2 (isc_arg_string)
[11]: RT.T_IMESTAMP
[12]: 1 (isc_arg_gds)
[13]: 336397208 (isc_dsql_line_col_error)
[14]: 4 (isc_arg_number)
[15]: 21 ()
[16]: 4 (isc_arg_number)
[17]: 5 ()
[18]: 0 (isc_arg_end)
---------------
[ 0]: 1 (isc_arg_gds)
[ 1]: 335544569 (isc_dsql_error)
[ 2]: 1 (isc_arg_gds)
[ 3]: 335544436 (isc_sqlerr)
[ 4]: 4 (isc_arg_number)
[ 5]: -206 ()
[ 6]: 1 (isc_arg_gds)
[ 7]: 335544578 (isc_dsql_field_err)
[ 8]: 1 (isc_arg_gds)
[ 9]: 335544382 (isc_random)
[10]: 2 (isc_arg_string)
[11]: RT.T_IMESTAMP
[12]: 1 (isc_arg_gds)
[13]: 336397208 (isc_dsql_line_col_error)
[14]: 4 (isc_arg_number)
[15]: 21 ()
[16]: 4 (isc_arg_number)
[17]: 5 ()
[18]: 1 (isc_arg_gds)
[19]: 335544382 (isc_random)
[20]: 2 (isc_arg_string)
[21]: Additional info
[22]: 0 (isc_arg_end)


Сообщение в IBExpert
Column does not belong to referenced table.
Dynamic SQL Error.
SQL error code = -206.
Column unknown.
RT.T_IMESTAMP.
At line 21, column 5.


Если мой блок поставить в начало
+
procedure HandleFBExcept2(AStatus: IStatus; AExcept: FbException);
var
  LLogger: ILogger;
  LStatus: NativeIntPtr;
  LCurStatus: NativeIntPtr;
  LNewStatus: array of NativeInt;
  LCnt: Integer;
begin
  LLogger := TLoggerFactory.GetLogger('ServiceArea');
  LStatus := AExcept.getStatus.getErrors;
  // Логируем текущий вектор
  ShowStatus(LLogger, LStatus);
  LCurStatus := LStatus;
  // Вычисляем длину вектора
  while LCurStatus^ <> isc_arg_end do begin
    if LCurStatus^ = isc_arg_cstring then
      Inc(LCurStatus, 3)
    else
      Inc(LCurStatus, 2);
  end;
  LCnt := (NativeInt(LCurStatus) - NativeInt(LStatus));
  // Выделяем память под новый вектор
  SetLength(LNewStatus, LCnt + 5);
    // Добавляем новый блок
  LNewStatus[0] := isc_arg_gds;
  LNewStatus[1] := isc_random;
  LNewStatus[2] := isc_arg_string;
  LNewStatus[3] := NativeInt(PAnsiChar('Additional info'));
  // Копируем старый вектор, в новый
  Move(LStatus^, LNewStatus[4], LCnt + SizeOf(LNewStatus[0]));
  AStatus.setErrors(@LNewStatus[0]);
  LLogger.Log('---------------');
  LStatus := AStatus.getErrors;
  // Логируем новый вектор
  ShowStatus(LLogger, LStatus);
  raise FbException.Create(AStatus);
end;

то получим такой вектор
+
[ 0]: 1 (isc_arg_gds)
[ 1]: 335544569 (isc_dsql_error)
[ 2]: 1 (isc_arg_gds)
[ 3]: 335544436 (isc_sqlerr)
[ 4]: 4 (isc_arg_number)
[ 5]: -206 ()
[ 6]: 1 (isc_arg_gds)
[ 7]: 335544578 (isc_dsql_field_err)
[ 8]: 1 (isc_arg_gds)
[ 9]: 335544382 (isc_random)
[10]: 2 (isc_arg_string)
[11]: RT.T_IMESTAMP
[12]: 1 (isc_arg_gds)
[13]: 336397208 (isc_dsql_line_col_error)
[14]: 4 (isc_arg_number)
[15]: 21 ()
[16]: 4 (isc_arg_number)
[17]: 5 ()
[18]: 0 (isc_arg_end)
---------------
[ 0]: 1 (isc_arg_gds)
[ 1]: 335544382 (isc_random)
[ 2]: 2 (isc_arg_string)
[ 3]: Additional info
[ 4]: 1 (isc_arg_gds)
[ 5]: 335544569 (isc_dsql_error)
[ 6]: 1 (isc_arg_gds)
[ 7]: 335544436 (isc_sqlerr)
[ 8]: 4 (isc_arg_number)
[ 9]: -206 ()
[10]: 1 (isc_arg_gds)
[11]: 335544578 (isc_dsql_field_err)
[12]: 1 (isc_arg_gds)
[13]: 335544382 (isc_random)
[14]: 2 (isc_arg_string)
[15]: RT.T_IMESTAMP
[16]: 1 (isc_arg_gds)
[17]: 336397208 (isc_dsql_line_col_error)
[18]: 4 (isc_arg_number)
[19]: 21 ()
[20]: 4 (isc_arg_number)
[21]: 5 ()
[22]: 0 (isc_arg_end)

и ошибку
Column does not belong to referenced table.
Additional info.
Dynamic SQL Error.
SQL error code = -206.
Column unknown.
RT.T_IMESTAMP.
At line <Missing arg #1 - possibly status vector overflow>, column <Missing arg #2 - possibly status vector overflow>.
16 июн 20, 16:36    [22151774]     Ответить | Цитировать Сообщить модератору
 Re: Добавление информации в StatusVector  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11911
Знаю, что варварство, но сделал так
procedure HandleFBExcept3(AUtil: IUtil; AExcept: FbException; const AName: string);
var
  LBuf: array[0..4095] of AnsiChar;
  LStatus: IStatus;
  LLen: Cardinal;
  LMsg: AnsiString;
begin
  LStatus := AExcept.getStatus;
  LLen := AUtil.formatStatus(@LBuf[0], Length(LBuf), LStatus);
  SetString(LMsg, PAnsiChar(@LBuf[0]), LLen);
  raise EUDRException.Create(AName + sLineBreak + string(LMsg));
end;
для моей задачи этого достаточно
16 июн 20, 17:21    [22151810]     Ответить | Цитировать Сообщить модератору
 Re: Добавление информации в StatusVector  [new]
hvlad
Member

Откуда:
Сообщений: 10954
_Vasilisk_
  LStatus: NativeIntPtr;
  LCurStatus: NativeIntPtr;
  LNewStatus: array of NativeInt;
  LCnt: Integer;
begin

  LCnt := (NativeInt(LCurStatus) - NativeInt(LStatus));
Гм... А что это тут происходит ? Указатели - в числа и разницу адресов вычисляем ?
И что тут получается ?

_Vasilisk_

...
[19]: 335544382 (isc_random)
[20]: 2 (isc_arg_string)
[21]: Additional info
[22]: 0 (isc_arg_end)

Сообщение в IBExpert
Ставлю на то, что он не понимает более 20 эл-тов в статусе, т.к. использует старое API.

Проверь в isql
16 июн 20, 18:30    [22151891]     Ответить | Цитировать Сообщить модератору
 Re: Добавление информации в StatusVector  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11911
hvlad
Гм... А что это тут происходит ? Указатели - в числа и разницу адресов вычисляем ?
Ну да. Определяем длину в байтах
hvlad
Ставлю на то, что он не понимает более 20 эл-тов в статусе, т.к. использует старое API.
Блин! Два дня убил.
hvlad
Проверь в isql
Тут все работает.

Как бы грамотно сформулировать баг-репорт на IBExpert
16 июн 20, 19:05    [22151913]     Ответить | Цитировать Сообщить модератору
 Re: Добавление информации в StatusVector  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 50343

_Vasilisk_
Как бы грамотно сформулировать баг-репорт на IBExpert

Бесполезно. Даже если кто-то это и посчитает за баг, то точно не в эксперте, а в fbclient,
который кривовато трансформирует новый длинный вектор в старый короткий, разрывая
сообщение посередине.

Posted via ActualForum NNTP Server 1.5

16 июн 20, 19:14    [22151917]     Ответить | Цитировать Сообщить модератору
 Re: Добавление информации в StatusVector  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11911
Dimitry Sibiryakov
то точно не в эксперте, а в fbclient,
А isql работает мимо fbclient?
16 июн 20, 19:24    [22151925]     Ответить | Цитировать Сообщить модератору
 Re: Добавление информации в StatusVector  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 50343

_Vasilisk_
А isql работает мимо fbclient?

isql работает мимо ISC_STATUS_ARRAY. Его уже перевели на новое API.

Posted via ActualForum NNTP Server 1.5

16 июн 20, 19:30    [22151931]     Ответить | Цитировать Сообщить модератору
 Re: Добавление информации в StatusVector  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11911
Dimitry Sibiryakov
Его уже перевели на новое API.
Оно реализовано в fbclient?

IBExpert уже пилится под FB4. Имхо, можно задуматься сразу и на переход на новый API.
17 июн 20, 12:59    [22152291]     Ответить | Цитировать Сообщить модератору
 Re: Добавление информации в StatusVector  [new]
Симонов Денис
Member

Откуда: Рязань
Сообщений: 10574
_Vasilisk_,

Это не так просто как ты думаешь. Из нового API для 4.0 в IBExpert пока только интерфейсы для поддержки новых типов используются
17 июн 20, 13:08    [22152300]     Ответить | Цитировать Сообщить модератору
Все форумы / Firebird, InterBase Ответить