![]() |
Referencias circulares aparentes con SPs
Hola de nuevo. Ahora entiendo bien lo del código BLR y el mensaje de error de IBConsole. Había comentado que tenía una solución, la puse en práctica y todo funcionó muy bien, pero siempre sucede algo nuevo, como lo que les voy a contar:
Supongamos que tengo el SP1 y el SP2. 1. El SP1 evalúa uno de sus parámetros (un código) y devuelve el valor calculado. 2. El SP2 evalúa una expresión matemática, pero en la cual algunos de los términos son códigos. Ahora, veamos: Ejecuto el SP1 pasándole como parámetro el código X, y él mismo determina que el código X que debe evaluar es de tipo fórmula, por lo cual llama a SP2. El SP2 recorre los términos de la expresión correspondiente al código X. Luego, cuando encuentra un código Z en dicha expresión, llama al SP1 para que éste lo evalúe. El SP1 evalúa el código Z, y es probable que éste sea nuevamente un código de tipo fórmula... ... Es claro que esta es una referencia circular pero siempre y cuando se repita en alguna llamada uno de los códigos anteriores. En mi caso, esto no sucede ya que una aplicación cliente verifica que no existan códigos repetidos, por lo cual nunca habrá un desbordamiento de pila o numérico. El problema que tengo, es que, aunque esto no suceda siempre, sobre todo con expresiones cortas, InterBase no me deja ejecutar los SPs. El error es el siguiente: "arithmetic exception, numeric overflow, or string truncation on line 1 : SELECT out_result FROM "PayFormValue"('X', ...) Pensé que de nuevo podría ser IBConsole, y lo probé desde Delphi 7. Generó de nuevo el mismo error. Intenté usar un procedimiento intermediario, pero tampoco funcionó. De nuevo, debo decir que estos procedimientos los estoy migrando de MS SQL Server a InterBase, y en SQL Server funcionaban bien. Quisiera saber si alguien ha tenido algún problema similar y cómo lo ha podido resolver. Muchas gracias por su colaboración. |
Ha sido un poco difícil llegar a esto, pero tuve que quitar todo el código posible para saber dónde estaba el error. Si alguien está dispuesto, esta es una invitación para que creen la siguiente table y el siguiente procedimiento almacenado:
Código:
CREATE TABLE "Tempo"( Código:
CREATE PROCEDURE "EvalExpr" ( Luego, los eliminamos: DELETE FROM "Tempo"; Volvemos a registrar unos cuantos que tengan el mismo valor, por ejemplo '000000'. Así la tabla podría verse más o menos así: Código:
Auto Value select out_result from "EvalExpr"('000000'); y voy a hablar de la línea: expr = STRCAT(expr, segexpr); Cuando hay menos de 27 registros en la tabla con el valor '000000' no hay problema. Si hay 27 registros o más... Se causa el error del que pensaba era causado por una referencia circular. Si se cambia la línea mencionada, digamos por: expr = STRCAT(expr, '**'); El problema desaparece, pero debe ser claro que esta línea es sumamente importante, casi el objeto del procedimiento almacenado, ya que en ella se construye una expresión que luego debe ser evaluada (en el ejemplo no se ve esto con claridad). ¿ Lo que estoy haciendo es muy importante... y me encontré con esto! ¿ ES UN BUG DE INTERBASE ? He hecho muchas pruebas, de muchas formas, y la verdad lo único que me falta es probar con otra función para concatenar. La función STRCAT que estoy usando es la proporcionada junto a InterBase, librería udflib.dll. Hubiese probado otra función pero no la he encontrado. Si alguien me pudiera ayudar agradecería mucho su colaboración. por si acaso, la función externa está declarada tal y como se especifica en la documentación, así: DECLARE EXTERNAL FUNCTION STRCAT VARCHAR(255) CHARACTER SET NONE, VARCHAR(255) CHARACTER SET NONE RETURNS CSTRING(80) CHARACTER SET NONE FREE_IT ENTRY_POINT 'fn_strcat' MODULE_NAME 'udflib'; |
Hola,
Cita:
Cita:
Nota para investigar: algunos problemas del uso de tipos cadena (CHAR y VARCHAR) provienen del juego de caracteres utilizado (en la base de datos y en las columnas implicadas). Saludos. |
Claro, no sé si es porque hace algún tiempo no trabaja en InterBase, o porque de trabajar en varios lenguajes se le confunden las cosas a uno en la cabeza, o porque cuando uno busca la sección operadores que toda referencia del lenguaje tiene sencillamente en la de InterBase no la encuentra. De cualquier forma todo esto suena como a disculpa... entonces prefiero pensar que tal vez todo se debió a la falta de sueño en los últimos días!
En la primera prueba que hice con el operador todo funcionó bien. Voy a probar con el conjunto de SPs auténticos del sistema. Gracias. |
Hola,
Cita:
"Concatenation operator ||, used to combine character strings." Volumen "Embedded SQL Guide", capítulo "Working with Data", "Understanding SQL expressions" De todas formas, coincido contigo, es algo que debería ir en la guía de referencia del lenguaje y no en un apartado escondido de la guía de SQL embebido. Saludos. |
No era necesaria la tabla. Veamos el siguiente SP:
Código:
ALTER PROCEDURE "EvalExpr" Claro, la variable i es decimal(18, 4) y tiene como mínimo 6 caracteres al ser convertida a varchar, así si i = 0 tenemos que cast(i as varchar(32)) = '0.0000'. cuando se cuenta hasta i < 33 se tienen exactamente 254 caracteres, valor justo por debajo del tamaño de la variable expr. Sucede que cuando un procedimiento tiene mucho más código, como InterBase no retorna el punto exacto donde está el error, pues la depuración es ardua y engorrosa, pero ahí vamos. |
Con respecto a tu último comentario, has citado la referencia:
Cita:
Definitivamente el error debe ser corregido. Gracias. |
La franja horaria es GMT +2. Ahora son las 22:23:33. |
Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi