2012-01-02 31 views
7

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.

+0

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

+0

@LaKraven - Ý bạn là gì? Không có cách nào để nhận được thông báo lỗi đầy đủ? –

+0

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

Trả lời

6

trái ngược với ý kiến ​​của người khác, tôi quyết định tinh chỉnh hơn nữa và cuối cùng đã tìm ra cách để tăng số lượng các nhân vật trong "hòa giải " thông báo lỗi. Khi tôi nghĩ rằng vấn đề là trong midas.dll, hoặc cụ thể hơn các nguồn tạo nên dll midas vì cùng một tập hợp các nguồn có thể tạo MidasLib, mà không yêu cầu một dll midas. Để giải quyết, tôi phải cài đặt tính cách Delphi C++ để biên dịch midas.

Sau khi tìm thấy lỗi, tôi phát hiện ra rằng thậm chí có yêu cầu sửa chữa cho QC (http://qc.embarcadero.com/wc/qcmain.aspx?d=84960) mà dường như đã bị bỏ qua bởi các nhân viên của Embarcadero, như là "Nghị quyết" như là "Trì hoãn để tiếp theo Rel "(hoãn để phát hành tiếp theo) nhưng yêu cầu là từ năm 2010 và tôi đang sử dụng xe Delphi mà theo ý kiến ​​của tôi nên có giải pháp nhưng ở đây tôi đang điều chỉnh một mình;)

Vấn đề nằm trong phương pháp "Sao chép" của lớp "DSBASE", bên trong nguồn "ds.cpp" tại dòng 2133 (Delphi XE, Update1). Dưới đây là khối mã. Đường màu đỏ là dòng có vấn đề:

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

Lưu ý rằng nó rất thú vị trong dòng sự cố. Nó có giá trị không đổi là 255, giới hạn kích thước của các thông báo lỗi và nhận xét "Tăng theo yêu cầu". Cũng lưu ý rằng bên cạnh nhận xét, có một hằng số DBIMAXMSGLEN, mà tôi đã tìm thấy và đã bị nghi ngờ là chịu trách nhiệm về vấn đề này, nhưng vì nó không được sử dụng, tôi đã thay đổi giá trị DBIMAXMSGLEN nhưng thông báo lỗi luôn đến mà không có thay đổi. Điều đáng nói rằng có một dấu chấm phẩy (;) sau DBIMAXMSGLEN dẫn tôi nghĩ rằng trước (tôi không biết khi nào) dòng này là một trong đó là ngay sau khi sửa chữa của tôi:

pFldDes->iUnits1 = DBIMAXMSGLEN; 

Đó là nếu một người nào đó đã cố tình đặt giá trị trường là 255, loại bỏ việc triển khai trước đó thực sự động và dường như chính xác hơn. Sau khi thực hiện thay thế dòng, tôi đã tăng giá trị của DBIMAXMSGLEN lên 1024. DBIMAXMSGLEN được khai báo là "bdetypes.h" làm định nghĩa. Sau khi sửa chữa đường đi như thế này:

#define DBIMAXMSGLEN   1024   // Max message len 

Sau hai sự thay đổi này trong "ds.cpp" và "bdetypes.h" Tôi xây dựng, kiểm tra, và kết quả được như mong đợi: thông báo lỗi đã được trình bày đầy đủ trong hộp thoại Reconcile.

Để người dũng cảm muốn thử xem họ có gặp vấn đề này không, bạn cần nguồn MIDAS, đi kèm với Delphi từ năm 2010 nếu tôi nhớ chính xác. Chúc mọi người may mắn.

+1

May mắn là ai đó không yêu cầu 32 hoặc một cái gì đó .. :) –

+0

@SertacAkyuz - Chính xác;) –

+0

Tôi đã đi xa hơn và trong việc thực hiện riêng của tôi về midas (dựa trên hyperbase) đã quyết định giải quyết vấn đề đó để giữ và thay đổi loại trường cơ bản từ chuỗi thành ghi nhớ – vavan

Các vấn đề liên quan