Tôi ở đây một lần nữa để yêu cầu trợ giúp cho bạn. Lần này tôi tin rằng một vài người sẽ phản ứng với tính đặc thù lớn của vấn đề mà tôi sẽ liên hệ. Tôi bắt đầu trong thế giới của DataSnap, và vẫn có những điều tôi không hiểu làm thế nào lỗi này tôi sẽ liên quan.Lỗi đối chiếu: Có ai có vấn đề với thông báo lỗi bị cắt ngắn không?
Delphi của tôi là XE (phiên bản 1, Update1). Tôi đang sử dụng Postgres tạo thông báo lỗi bằng tiếng Bồ Đào Nha (Bồ Đào Nha Braxin) và vì lý do này các thông báo lỗi có dấu trọng âm. Các thành phần kết nối là gói ZeosLib.
Tôi đang sử dụng hộp thoại "sửa lỗi" để hiển thị lỗi phát sinh từ ứng dụng cập nhật và thử nghiệm, tôi đã cố gắng chèn bản ghi đã tồn tại, do đó vi phạm khóa duy nhất và do đó hiển thị hộp thoại sửa lỗi.
Trong bản ghi nhớ của hộp thoại, thông báo xuất hiện bị cắt ngắn, tức là cắt. Check it out:
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
Nhưng trên thực tế những gì nên được trả lại này là:
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
Tôi đã làm một debug trên máy chủ để xem nếu vấn đề là ZeosLib, nhưng tôi thấy rằng các thông báo lỗi được tạo trên máy chủ hoàn tất, chứng minh rằng ZeosLib không cắt xén tin nhắn. Mọi thứ đều là unicode. Tất cả các chuỗi là WideString (mặc định) trên cả chương trình của tôi và trong ZeosLib.
Như bạn đã biết, được ném trên máy chủ, ngoại lệ được chuyển tiếp tới máy khách, bằng cách nói, bởi DataSnap và trên máy khách, phương pháp Reconcile của TClientDataSet xác minh nếu có vấn đề và sau đó ném ngoại lệ nổi tiếng EReconcileError có thể được xử lý trong sự kiện OnReconcileError của TClientDataSet, do đó tôi tin rằng thông báo đang được cắt ngắn bởi DataSnap. Trên máy khách, tôi gỡ lỗi phương thức Reconcile (DBClient.pas) và ngay trước khi ngoại lệ được ném luồng vào một hàm trong mã nguồn cpp mà tôi nghĩ là một phần của thư viện midas.dll, MidasLib.obj cụ thể hơn , vì tôi đang sử dụng chiến lược này, không phải phân phối DLL với ứng dụng của tôi.
Check(FDSBase.Reconcile_MD(FReconcileDataSet.FDSBase, FDeltaPacket, VarToDataPacket(Results), Integer(Self), RCB));
Cuộc gọi này được thực hiện tại dòng 1952 của đơn vị DBClient.pas trên Delphi XE Update1. Nhấn F7, trình gỡ rối nhập vào nguồn C++ (cpp), vì vậy tôi tin rằng nó nằm trong midaslib.obj. Làm thế nào tôi không hiểu C++ tốt, tôi nhấn Shift-F8 để thoát khỏi phương thức hiện tại và trả về lệnh tiếp theo, đã nằm trong sự kiện OnReconcileError !! Vì vậy, việc cắt ngắn phải được thực hiện trong hàm tôi đã đề cập, trong một nguồn cpp, trong phạm vi midaslib.
Mục đích của tôi là làm cho hộp thoại Khắc phục lỗi là một công cụ không chỉ cho người dùng cuối cùng mà còn hỗ trợ cá nhân, cung cấp thông tin riêng về Lỗi, Chi tiết và Ngữ cảnh. Điều này giúp rất nhiều để khám phá một vấn đề.
Vấn đề bây giờ là làm cho thông báo xuất hiện đầy đủ. Có ai có loại vấn đề này với các tin nhắn bị cắt ngắn bởi midas không?
Ngoài ra một điểm DSClient.pas tôi có thể trích xuất các thông báo lỗi khi nó được truyền cho các ngoại lệ:
'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'
Nếu bạn loại bỏ các dấu ngoặc kép và thay thế # $ A (1 ký tự) bởi một khoảng trắng (một ký tự), bạn sẽ thấy rằng chuỗi có chính xác 255 ký tự !!
Tôi cũng phát hiện ra rằng "GetErrorString" trong dspickle.cpp sử dụng hằng số DBIMAXMSGLEN được định nghĩa trong bdetypes.h là 127 (một nửa 255). Như chúng ta đang ở trong thế giới của Unicode, nó sẽ không là một câu hỏi tăng giá trị này lên 255 để có hai byte cho mỗi ký tự? Đây chỉ là một dự đoán ...
Tôi để lại câu hỏi trong không khí vì tôi thiếu kiến thức để hiểu C++ :) Ai có thể giúp, chỉ cần nhìn vào việc thực hiện chức năng "GetErrorString" trong dspickle.cpp. Có là thế này:
LoadString((HINSTANCE)hDll, iErrCode, pString, DBIMAXMSGLEN)
pString là thông báo lỗi và DBIMAXMSGLEN = 127.
Trong trường hợp lỗi SQL, thường là Nhà cung cấp cơ sở dữ liệu cắt thông báo lỗi và nằm ngoài phạm vi mã Delphi của bạn (nghĩa là vấn đề là với Nhà cung cấp cơ sở dữ liệu thay vì Delphi hoặc mã của bạn). – LaKraven
@LaKraven - Ý bạn là gì? Không có cách nào để nhận được thông báo lỗi đầy đủ? –
Nếu trong trường hợp này, Nhà cung cấp Cơ sở dữ liệu của bạn cắt xén thông báo lỗi, thì có ... không có cách nào để nhận được tin nhắn đầy đủ (trừ khi bạn có thể cấu hình lại nhà cung cấp để gửi tin nhắn đầy đủ?) – LaKraven