2012-01-02 18 views
7

Estoy aquí nuevamente para pedirte ayuda. Esta vez creo que pocos responderán dada la gran particularidad del problema que relataré. Estoy comenzando en el mundo de DataSnap, y todavía tengo cosas que no entiendo cómo relacionaré este error.Reconcile Error: ¿Alguien ha tenido problemas con los mensajes de error truncados?

Mi Delphi es XE (versión 1, actualización 1). Estoy usando Postgres que genera mensajes de error en portugués (portugués de Brasil) y por esta razón los mensajes de error tienen acentos. Los componentes de conexión son paquete ZeosLib.

Estoy usando un cuadro de diálogo "reconciliar error" para mostrar errores derivados de la aplicación de actualizaciones y para probar, traté de insertar un registro que ya existía, violando así una clave única y mostrando así el cuadro de diálogo de error de conciliación.

En la nota del cuadro de diálogo, el mensaje que aparece se trunca, es decir, se corta. Compruébelo usted mismo:

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 

Pero en realidad lo que debe ser devuelta es la siguiente:

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 

he hecho una depuración en el servidor para ver si el problema es ZeosLib, pero me encontré con que el mensaje de error generado en el servidor está completo, lo que demuestra que ZeosLib no trunca el mensaje. Todo es unicode Todas las cadenas son WideString (por defecto) tanto en mi programa como en ZeosLib.

Como usted sabe, para lanzarse al servidor, la excepción se reenvía al cliente, en términos generales, por DataSnap, y en el cliente, el método Reconciliar de TClientDataSet verifica si hubo problemas y luego lanza la famosa excepción EReconcileError que se puede manejar en el evento OnReconcileError de TClientDataSet, por lo tanto, creo que el mensaje está siendo truncado por DataSnap.

En el cliente, debo depurar el método Reconcile (DBClient.pas) e inmediatamente antes de que se produzca la excepción, el flujo entra en una función dentro de un código fuente cpp que creo que forma parte de la biblioteca midas.dll, MidasLib.obj más específicamente , ya que estoy usando esta estrategia, no tengo que distribuir el archivo DLL con mi aplicación.

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

Esta llamada se realiza en la línea 1952 de los DBClient.pas unidad de Delphi XE Update1. Presionando F7, el depurador ingresa una fuente C++ (cpp), así que creo que está dentro de midaslib.obj. Como no entiendo bien C++, presiono Shift-F8 para salir del método actual y devolver la siguiente instrucción, que ya está dentro del evento OnReconcileError !! Por lo tanto, el truncamiento debe realizarse dentro de la función que mencioné, dentro de una fuente de cpp, dentro de midaslib.

Mi intención es hacer que el cuadro de diálogo Reconciliar error sea una herramienta no solo para el usuario final, sino también para dar soporte a los personales, proporcionando por separado información de Error, Detalles y Contexto. Esto ayuda mucho a descubrir un problema.

El problema ahora es hacer que el mensaje aparezca completo. ¿Alguien ha tenido este tipo de problema con mensajes truncados por midas?

también otro punto de DSClient.pas pude extraer el mensaje de error, ya que se pasa a la excepción:

'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' 

Si quita las comillas y reemplazar # $ A (1 carácter) por un espacio en blanco (un personaje), verás que la cadena tiene exactamente 255 caracteres.

También descubrí que el "GetErrorString" en dspickle.cpp usa el DBIMAXMSGLEN constante que se define en bdetypes.h como 127 (la mitad de 255). Como estamos en el mundo de Unicode, no se trata de aumentar este valor a 255 para tener dos bytes por carácter. Esto es solo una suposición ...

Dejo la pregunta en el aire porque no tengo el conocimiento para entender C++ :) Quien puede ayudar, solo mire la implementación de la función "GetErrorString" en dspickle.cpp. No es éste:

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

PString es el mensaje de error y DBIMAXMSGLEN = 127.

+0

En casos de errores de SQL, generalmente el Proveedor de bases de datos trunca el mensaje de error y está fuera del alcance de su código Delphi (lo que significa que el problema está en el proveedor de la base de datos en lugar de Delphi o su código). – LaKraven

+0

@LaKraven - ¿Qué quieres decir? No hay forma de obtener el mensaje de error completo? –

+0

Si en este caso es su proveedor de base de datos truncar el mensaje de error, entonces sí ... no hay forma de obtener el mensaje completo (a menos que pueda reconfigurar el proveedor para dar mensajes completos?) – LaKraven

Respuesta

6

En contradicción con la opinión de los demás decidí ajustar aún más y finalmente descubierto la manera de aumentar el número de caracteres en el "Conciliar " mensaje de error. Como yo pensaba que el problema estaba en midas.dll, o más específicamente en las fuentes que componen el dll de midas porque el mismo conjunto de fuentes puede crear MidasLib, que no requiere un dll de midas. Para resolver tuve que instalar la personalidad de Delphi C++ para compilar el midas.

Después de encontrar la línea del error, descubrí que incluso hay una solicitud de reparaciones al control de calidad (http://qc.embarcadero.com/wc/qcmain.aspx?d=84960) que parece haber sido ignorada por el personal de Embarcadero, ya que la "Resolución" es "diferida" a Next Rel "(diferido a la próxima versión) pero la solicitud es de 2010 y estoy usando Delphi XE, que en mi opinión debería tener la solución, pero aquí estoy corrigiendo por mí mismo;)

El problema está en el método "Clonar" de la clase "DSBASE", dentro de la fuente "ds.cpp" en la línea 2133 (Delphi XE, Update1). Debajo está el bloque de código. La línea roja es la línea problemática:

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

Tenga en cuenta que es muy interesante la línea del problema. Tiene un valor constante de 255, que limita el tamaño de los mensajes de error y un comentario "Aumentado a petición". También tenga en cuenta que, al lado del comentario, hay una constante DBIMAXMSGLEN, que había encontrado y que ya sospechaba que era el responsable del problema, pero como no se usaba, cambié el valor de DBIMAXMSGLEN pero el mensaje de error siempre aparecía sin cambios. Vale la pena mencionar que hay un punto y coma (;) después DBIMAXMSGLEN que me lleva a pensar que antes (no sé cuando) esta línea era una que estaba justo después de mi dosis:

pFldDes->iUnits1 = DBIMAXMSGLEN; 

Es como si alguien había establecido deliberadamente el valor de campo en 255, eliminando la implementación anterior que era realmente dinámica y aparentemente más correcta. Después de realizar el reemplazo de la línea, aumenté el valor de DBIMAXMSGLEN a 1024. DBIMAXMSGLEN se declaró "bdetypes.h" como definición. Después de corregir la línea era la siguiente:

#define DBIMAXMSGLEN   1024   // Max message len 

Después de estos dos cambios en "ds.cpp" y "bdetypes.h" Me construir, probar, y el resultado fue el esperado: el mensaje de error se presentó en su totalidad en el cuadro de diálogo Reconciliar.

Para los valientes que quieran probar si han visto este problema, necesitas las fuentes de MIDAS, que vienen con Delphi de 2010 si no recuerdo mal. Buena suerte a todos.

+1

Afortunado de que alguien no lo solicitó ser 32 o algo así :) :) –

+0

@SertacAkyuz - Exactamente;) –

+0

Fui más lejos y en mi propia implementación de midas (basado en hyperbase) decidí resolver ese problema para siempre y cambié el tipo de campo subyacente de cadena a memo – vavan

Cuestiones relacionadas