Ошибка согласования: у кого-нибудь были проблемы с усеченными сообщениями об ошибках?
я снова здесь, чтобы попросить вас о помощи. На этот раз, я полагаю, мало кто ответит, учитывая большую специфику проблемы, о которой я расскажу. Я начинаю в мире DataSnap, и все еще есть вещи, которые я не понимаю, как эта ошибка будет относиться.
мой Delphi-XE (Версия 1, Update1). Я использую 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, а на клиенте метод согласования TClientDataSet проверяет, были ли проблемы, а затем бросьте знаменитое исключение EReconcileError, которое может быть обработано в событии OnReconcileError TClientDataSet, поэтому я считаю, что сообщение усекается DataSnap.
на клиенте я отлаживаю метод согласования (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.
мое намерение состоит в том, чтобы сделать диалог согласования ошибок инструментом не только для конечного пользователя, но и для поддержки личных данных, предоставляя отдельно информацию об ошибке, деталях и контексте. Это помогает обнаружить проблему.
теперь проблема заключается в том, чтобы сообщение появилось полностью. У кого-нибудь были такие проблемы с сообщениями, усеченными Мидасом?
также еще один пункт 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.СРР. Есть такое:
LoadString((HINSTANCE)hDll, iErrCode, pString, DBIMAXMSGLEN)
pString-это сообщение об ошибке и DBIMAXMSGLEN = 127.
1 ответов
противореча мнению других, я решил настроить дальше и, наконец, понял, как увеличить количество символов в сообщении об ошибке "согласовать". Как я и думал проблема была в Мидас.dll, или, более конкретно, источники, которые составляют Midas dll, потому что тот же набор источников может создать MidasLib, который не требует midas dll. Чтобы решить эту проблему, мне пришлось установить личность Delphi C++ для компиляции midas.
после нахождения строки ошибки, I обнаружил, что есть даже запрос на ремонт КК (http://qc.embarcadero.com/wc/qcmain.aspx?d=84960) который, похоже, был проигнорирован сотрудниками Embarcadero, так как" резолюция "как" отложена до следующего Rel " (отложена до следующего выпуска), но запрос с 2010 года, и я использую Delphi XE, который, на мой взгляд, должен иметь решение, но здесь я исправляю сам ;)
проблема находится внутри метода "клон" класса "DSBASE", внутри источник "ДС.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 года, если я правильно помню. Удачи всем.