2012-01-02 6 views
7

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

My 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.

Я намерен сделать диалог Reconcile Error инструментом не только для конечного пользователя, но и для поддержки знакомств, предоставляя отдельную информацию об ошибках, деталях и контексте. Это помогает обнаружить проблему.

Проблема заключается в том, чтобы сообщение появилось в полном объеме. Кто-нибудь имел такую ​​проблему, когда сообщения были усечены мидасом?

и другая точка 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.

+0

В случае ошибок SQL обычно поставщик базы данных обрезает сообщение об ошибке и выходит за рамки вашего кода Delphi (это означает, что проблема связана с поставщиком баз данных, а не с Delphi или вашим кодом). – LaKraven

+0

@LaKraven - Что ты имеешь в виду? Нет способа получить полное сообщение об ошибке? –

+0

Если в этом случае ваш поставщик баз данных усекает сообщение об ошибке, то да ... нет способа получить полное сообщение (если вы не можете перенастроить провайдера на получение полных сообщений?) – LaKraven

ответ

6

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

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

Проблема заключается в методе «Клон» класса «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» я строй, испытании, и результат, как и ожидалось: сообщение об ошибке было представлено в полном объеме в диалоговом окне Reconcile.

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

+1

К счастью, кто-то не просил его быть 32 или что-то .. :) –

+0

@SertacAkyuz - Точно;) –

+0

Я пошел дальше и в своей собственной реализации midas (на основе гипербазы) решил решить эту проблему для сохранения и изменения типа базового поля из строки в памятку – vavan

 Смежные вопросы

  • Нет связанных вопросов^_^