Ошибка согласования: у кого-нибудь были проблемы с усеченными сообщениями об ошибках? - PullRequest
7 голосов
/ 02 января 2012

Я снова здесь, чтобы попросить вас о помощи.На этот раз я верю, что мало кто ответит, учитывая большую специфику проблемы, с которой я столкнусь.Я начинаю в мире DataSnap, и все еще есть вещи, которые я не понимаю, как эта ошибка будет связана.

Мой Delphi - это XE (версия 1, обновление 1).Я использую Postgres, который генерирует сообщения об ошибках на португальском языке (португальский Бразилия), и по этой причине сообщения об ошибках имеют акценты.Компоненты подключения представляют собой пакет ZeosLib.

Я использую диалоговое окно «Ошибка согласования» для отображения ошибок, возникающих в результате применения обновлений, и для проверки я попытался вставить уже существующую запись, нарушив тем самым уникальнуюи, таким образом, отобразить диалоговое окно ошибки согласования.

В памятке диалогового окна появившееся сообщение обрезается, т.е.Проверьте это:

ERRO:  duplicar valor da chave viola a restrição de unicidade "uc_usu_va_login"
DETAIL:  Chave (va_login)=(admin) já existe.
CONTEXT:  comando SQL "INSERT INTO USUARIOS (VA_NOME
                           ,VA_LOGIN
                           ,CH

Но на самом деле, что должно быть возвращено, это:

ERRO:  duplicar valor da chave viola a restrição de unicidade "uc_usu_va_login"
DETAIL:  Chave (va_login)=(admin) já existe.
CONTEXT:  comando SQL "INSERT INTO USUARIOS (VA_NOME
                               ,VA_LOGIN
                               ,CH_SENHA
                               ,VA_EMAIL)
                        VALUES (pVA_NOME
                               ,pVA_LOGIN
                               ,pCH_SENHA
                               ,pVA_EMAIL)"
    PL/pgSQL function "idu_usuarios" line 7 at comando SQL

Я сделал отладку на сервере, чтобы увидеть, если проблема в ZeosLib, но я нашелчто сообщение об ошибке, сгенерированное на сервере, завершено, доказывая, что ZeosLib не усекает сообщение.Все в юникоде.Все строки имеют WideString (по умолчанию) как в моей программе, так и в ZeosLib.

Как вы знаете, для выдачи на сервер исключение перенаправляется клиенту, грубо говоря, через DataSnap и наклиент, метод Reconcile из TClientDataSet проверяет наличие проблем, а затем выдает известное исключение EReconcileError, которое может быть обработано в событии OnReconcileError объекта TClientDataSet, поэтому я считаю, что сообщение усекается с помощью DataSnap.

Наклиент Я отлаживаю метод Reconcile (DBClient.pas) и непосредственно перед тем, как генерируется исключение, поток входит в функцию в исходном коде cpp, который, на мой взгляд, является частью библиотеки midas.dll, MidasLib.obj, поскольку я использую этотстратегия, чтобы не распространять DLL вместе с моим приложением.

Check(FDSBase.Reconcile_MD(FReconcileDataSet.FDSBase, FDeltaPacket, VarToDataPacket(Results), Integer(Self), RCB));

Этот вызов выполняется в строке 1952 блока DBClient.pas в Delphi XE Update1.Нажав клавишу F7, отладчик вводит исходный код C ++ (cpp), поэтому я считаю, что он находится внутри midaslib.obj.Как я плохо понимаю C ++, я нажимаю Shift-F8, чтобы выйти из текущего метода и вернуть следующую инструкцию, которая уже находится внутри события OnReconcileError !!Поэтому усечение должно быть выполнено в упомянутой мной функции внутри источника cpp внутри midaslib.

Мое намерение состоит в том, чтобы сделать диалог «Ошибка согласования» инструментом не только для конечного пользователя, но и для поддержки личных данных, обеспечиваяотдельно информация об ошибке, деталях и контексте.Это очень помогает обнаружить проблему.

Теперь проблема в том, чтобы сообщение появилось полностью.У кого-нибудь была такая проблема с сообщениями, усеченными midas?

Также еще один пункт DSClient.pas Я мог бы извлечь сообщение об ошибке, поскольку оно передается в исключение:

'Erro SQL: ERRO:  duplicar valor da chave viola a restrição de unicidade "uc_usu_va_login"'#$A'DETAIL:  Chave (va_login)=(admin) já existe.'#$A'CONTEXT:  comando SQL "INSERT INTO USUARIOS (VA_NOME'#$A'                           ,VA_LOGIN'#$A'                           ,CH'

Есливы удалите кавычки и замените # $ A (1 символ) пробелом (один символ), вы увидите, что строка содержит ровно 255 символов !!

Я также обнаружил, что "GetErrorString" в dspickle.cpp использует константу DBIMAXMSGLEN, которая определена в bdetypes.h как 127 (половина из 255).Поскольку мы находимся в мире Unicode, не стоит ли увеличивать это значение до 255, чтобы иметь два байта на символ?Это только предположение ...

Я оставляю вопрос в воздухе, потому что мне не хватает знаний, чтобы понять C ++ :) Кто может помочь, просто посмотрите на реализацию функции "GetErrorString" в dspickle.cpp.Есть это:

LoadString((HINSTANCE)hDll, iErrCode, pString, DBIMAXMSGLEN)

pString - сообщение об ошибке и DBIMAXMSGLEN = 127.

1 Ответ

6 голосов
/ 03 января 2012

Вопреки мнению других, я решил еще немного доработать и, наконец, выяснил, как увеличить количество символов в сообщении об ошибке «Согласовать». Как я и думал, проблема была в midas.dll или, точнее, в источниках, составляющих dll midas, потому что один и тот же набор источников может создавать MidasLib, для которой не требуется dll midas. Чтобы решить эту проблему, мне пришлось установить личность Delphi C ++ для компиляции midas.

Обнаружив строку ошибки, я обнаружил, что есть даже запрос на ремонт КК (http://qc.embarcadero.com/wc/qcmain.aspx?d=84960), который, похоже, был проигнорирован персоналом Embarcadero, так как «Резолюция» как "Отложено до следующей версии" (Отложено до следующей версии), но запрос от 2010 года, и я использую Delphi XE, который, по моему мнению, должен иметь решение, но здесь я исправляю сам;)

Проблема в методе "Clone" класса "DSBASE", в источнике "ds.cpp" в строке 2133 (Delphi XE, Update1). Ниже приведен блок кода. Красная линия - проблемная линия:

// Set the third field for the error string.
LdStrCpy((pCHAR)pFldDes->szName, szdsERRMESSAGE);
pFldDes->iFldType = fldZSTRING;
pFldDes->iUnits1 = 255; // Increased on request.. DBIMAXMSGLEN;
pFldDes++;

Обратите внимание, что очень интересна проблемная линия. Он имеет постоянное значение 255, что ограничивает размер сообщений об ошибках и комментария «Увеличивается по запросу». Также обратите внимание, что рядом с комментарием есть константа DBIMAXMSGLEN, которую я обнаружил и уже подозревал как ответственную за проблему, но так как она не использовалась, я менял значение DBIMAXMSGLEN, но сообщение об ошибке всегда пришли без изменений. Стоит отметить, что после DBIMAXMSGLEN стоит точка с запятой (;), что заставляет меня думать, что раньше (я не знаю, когда) эта строка была той, которая была сразу после моего исправления:

pFldDes->iUnits1 = DBIMAXMSGLEN;

Это как если бы кто-то преднамеренно установил значение поля 255, удалив предыдущую реализацию, которая была действительно динамичной и, казалось бы, более правильной. После выполнения замены строки я увеличил значение DBIMAXMSGLEN до 1024. DBIMAXMSGLEN объявляется как "bdetypes.h" как определение. После исправления строка пошла так:

#define DBIMAXMSGLEN         1024           // Max message len

После этих двух изменений в «ds.cpp» и «bdetypes.h» я строю, тестирую, и результат был таким, как ожидалось: сообщение об ошибке было представлено полностью в диалоговом окне «Согласовать».

Для смелых, которые хотят попробовать, если они видели эту проблему, вам нужны источники MIDAS, который поставляется с Delphi с 2010 года, если я правильно помню. Удачи всем.

...