Hola,
Me encontré con un extraño error en dbExpress que, aunque lo solucioné, me preocupa bastante porque no debería ocurrir en una tecnología con la madurez que debería tener dbExpress. Corresponde a casos muy comunes; así que su corrección y detección implica un esfuerzo muy grande cuando se está migrando. Por ello quiero comentarselos.
La historia es así:
El siguiente comando SQL me está generando el error "Field Name missing":
Código SQL
[-]Select Sum(AREAESPACIO) From PLANTAFISICA
Where (CODIGOENCUES = :ACode)
Para analizar el error, hice una pequeña aplicación solo con un componente TSQLConnection y uno TSQLQuery, a fin de descartar cualquier problema generado por algún error previo en la aplicación original. Esta es la rutina que ejecuta el query:
Código Delphi
[-]Function TForm1.GetAreaPredioOtrosPisosDbX(ACode:String)
ouble;
Const
ELERROR = 'Error en %s por "%s"';
Begin
GetAreaPredioOtrosPisosDbX := 0;
Try
With SQLAreaOtrPisoDBx Do Begin
Active := False;
If Not Prepared Then Begin
Prepared := True;
End;
Params[0].AsString := ACode;
Try
Active := True;
If (Not IsEmpty) And (Not Fields[0].IsNull) Then Begin
GetAreaPredioOtrosPisosDbX := Fields[0].AsFloat;
End;
Finally
Active := False;
End;
End;
Except
On E:Exception Do Begin
raise Exception.CreateFmt(ELERROR,[ACode,E.Message]);
End;
End;
End;
Las consideraciones son las siguientes:
1. Uso Delphi 2007 Update 1 con Interbase y estoy migrando una aplicación BDE a dbExpress. Es la primera vez que uso dbExpress
2. Obviamente, la rutina trabaja perfectamente en Delphi 4 con BDE y también la probé en Delphi 2007 con BDE (lógicamente cambiando el Prepared := True por Prepare)
3. El DataType y el ParamType para el parámetro ACode están ajustados a ftString y ptInput
4. El DFM lo revisé internamente y está bien.
5. Si se intenta usar el editor de campos sobre el TSQlQuery, la opción Add All Fields genera el mismo error y la opción Add Fields no muestra ningún campo disponible
6. El Error se dispara en código al ejecutar Active := True
7. Si en lugar de usar Sum() se utiliza la función Count() el query trabaja bien.
La solución que encontré fué darle un nombre en el Query a la función Sum(); es decir, el siguiente comando trabaja bien:
Código SQL
[-]Select Sum(AREAESPACIO) ELAREA From PLANTAFISICA
Where (CODIGOENCUES = :ACode)
INFORMACIÓN ADICIONAL
Lo he rastreado dentro del código Delphi, por falta de tiempo solo hasta donde he podido, y me he encontrado con lo siguiente:
En el programa ejemplo, el depurador, al usar F7 (paso a paso) sobre Active me conduce a la unidad dbXCommon; pero la rutina SetActive que implementa la parte de escritura de la propiedad Active, en la jerarquía de TSQLQuery, según los fuentes Delphi, es la del ancestro TDataSet; o sea que no está redefinida para dbExpress (solo algunas rutinas internas de ella). Vale anotar que en este caso el depurador sigue una ruta que no muestra donde se produce el error mencionado
Lo anterior pone en evidencia otro error porque la jerarquía indicada la verifique en la versión original de la rutina. Me explicó: He desarrollado una emulación de BDE con componentes descendientes de los homólogos dbExpress; el componente original que uso en la rutina no es el
del ejemplo de prueba sino un TQuery (descendiente de TSQLQuery) y al rastrear ahí su propiedad Active el depurador conduce efectivamente al SetActive de TDataset. Ahí muestra que el error se genera porque la variable FFieldName del objeto TField está quedando en blanco.
INFORMACIÓN EN BORLAND
Hay dos reportes en Borland sobre "Field Name missing" que relatan casos muy parecidos:
http://qc.borland.com/wc/qcmain.aspx?d=49237
http://qc.borland.com/wc/qcmain.aspx?d=14435
Claramente, el fondo del problema es el mismo; sin embargo, hay diferencias sutiles con el que describo. Lo más preocupante es que el reporte 14435 está desde Delphi 7