Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 06-07-2003
Avatar de mlara
[mlara] mlara is offline
Miembro Premium
 
Registrado: jun 2003
Ubicación: Colombia
Posts: 667
Poder: 21
mlara Va por buen camino
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.
__________________
...y mañana caminaré por las calles pasando inadvertido, como siempre.
Responder Con Cita
  #2  
Antiguo 06-07-2003
Avatar de mlara
[mlara] mlara is offline
Miembro Premium
 
Registrado: jun 2003
Ubicación: Colombia
Posts: 667
Poder: 21
mlara Va por buen camino
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"(
  "Auto" INTEGER NOT NULL PRIMARY KEY,
  "Value" VARCHAR(6)
);

CREATE GENERATOR "Tempo_Auto";
SET GENERATOR "Tempo_Auto" TO 0;

CREATE TRIGGER "TAutoInc_Tempo" FOR "Tempo"
 BEFORE INSERT
 POSITION 0
AS BEGIN
 NEW."Auto" = GEN_ID("Tempo_Auto", 1);
END;
Código:
CREATE PROCEDURE "EvalExpr" (
  in_value VARCHAR(6))
  RETURNS(
  out_result DECIMAL(18, 4))

AS

DECLARE VARIABLE expr VARCHAR(256);
DECLARE VARIABLE segexpr VARCHAR(32);
DECLARE VARIABLE autoinc INTEGER;

BEGIN

  FOR
    SELECT "Auto"
    FROM "Tempo"
    WHERE "Value" = :in_value
    ORDER BY "Auto"
    INTO :autoinc
  DO BEGIN
    segexpr = CAST(autoinc AS VARCHAR(32));
    expr = STRCAT(expr, segexpr);
  END

  out_result = 1;

  SUSPEND;
END
Ahora, hay que hacer algunos registros en la tabla "Tempo", digamos unos 30 o más (yo hice cerca de 200 registros).

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
----    ----
35      000000
36      000000
37      000000
38      000000
39      000000
40      000000
41      000000
42      000000
43      000000
44      000000
45      000000
46      000000
...
Ahora, se ejecuta el SP:

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';
__________________
...y mañana caminaré por las calles pasando inadvertido, como siempre.
Responder Con Cita
  #3  
Antiguo 06-07-2003
Avatar de kinobi
kinobi kinobi is offline
Miembro
 
Registrado: may 2003
Posts: 2.621
Poder: 23
kinobi Va por buen camino
Hola,

Cita:
Posteado originalmente por mlara
He hecho muchas pruebas, de muchas formas, y la verdad lo único que me falta es probar con otra función para concatenar.
¿Has probado con el operador de concatenación, || (dos caracteres ASCII 124 seguidos)?.

Cita:
Posteado originalmente por mlara
La función STRCAT que estoy usando es la proporcionada junto a InterBase, librería udflib.dll.
Si el problema está en una UDF, se podría descartar casi con toda seguirdad un bug del servidor.

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.
Responder Con Cita
  #4  
Antiguo 06-07-2003
Avatar de mlara
[mlara] mlara is offline
Miembro Premium
 
Registrado: jun 2003
Ubicación: Colombia
Posts: 667
Poder: 21
mlara Va por buen camino
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.
__________________
...y mañana caminaré por las calles pasando inadvertido, como siempre.
Responder Con Cita
  #5  
Antiguo 06-07-2003
Avatar de kinobi
kinobi kinobi is offline
Miembro
 
Registrado: may 2003
Posts: 2.621
Poder: 23
kinobi Va por buen camino
Hola,

Cita:
Posteado originalmente por mlara
o porque cuando uno busca la sección operadores que toda referencia del lenguaje tiene sencillamente en la de InterBase no la encuentra.
es cierto que en el volumen "Language Reference" de la documentación no aparece la referencia al operador de concatenación (algo que debería ser corregido), pero también es cierto que sí viene en la documentación:

"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.
Responder Con Cita
  #6  
Antiguo 06-07-2003
Avatar de mlara
[mlara] mlara is offline
Miembro Premium
 
Registrado: jun 2003
Ubicación: Colombia
Posts: 667
Poder: 21
mlara Va por buen camino
No era necesaria la tabla. Veamos el siguiente SP:

Código:
ALTER PROCEDURE "EvalExpr"
  RETURNS(
  out_expr VARCHAR(256))

AS

DECLARE VARIABLE i DECIMAL(18, 4);
DECLARE VARIABLE expr VARCHAR(256);
DECLARE VARIABLE segexpr VARCHAR(32);

BEGIN

  expr = '';

  i = 0;
  WHILE (i < 34) DO BEGIN

    segexpr = CAST(i AS VARCHAR(32));
    expr = expr || segexpr;

    segexpr = '+';
    expr = expr || segexpr;

    i = i+1;
  END

  out_expr = expr;

  SUSPEND;
END
En este procedimiento se produce el mismo error cuando se cuenta hasta i < 34. Si se suenta hasta i < 33 no hay error.

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.
__________________
...y mañana caminaré por las calles pasando inadvertido, como siempre.
Responder Con Cita
  #7  
Antiguo 06-07-2003
Avatar de mlara
[mlara] mlara is offline
Miembro Premium
 
Registrado: jun 2003
Ubicación: Colombia
Posts: 667
Poder: 21
mlara Va por buen camino
Con respecto a tu último comentario, has citado la referencia:

Cita:
Volumen "Embedded SQL Guide", capítulo "Working with Data", "Understanding SQL expressions"
Eso lo entiendo, y aunque hace más o menos unos un año y medio trabajé con SQL embebido, pues no lo recordaba. Además precisamente ahora no estoy trabajando con SQL embebido, por lo que no he considerado necesario tener siquiera abierta la referencia citada.

Definitivamente el error debe ser corregido.

Gracias.
__________________
...y mañana caminaré por las calles pasando inadvertido, como siempre.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 12:27:15.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi