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 09-03-2010
subzero subzero is offline
No confirmado
 
Registrado: ene 2004
Ubicación: Móntería - Córdoba - Colombia
Posts: 289
Poder: 0
subzero Va por buen camino
Question UDF Firebird

Hola foreros.

Tras la necesidad de generar ciertos calculos dentro de una consulta y por la cantidad de datos para dicha operación, me he puesto a realizar una dll simple desde delphi 2005 la cual incluye unicamente la función que se debe ejecutar a la cual recibe los parametros por valor, pués bien hasta aqui todo bien, vinculo la dll y hago el llamamiento de la función desde firebird (ver 2.1) y en m equipo funciona perfecto!....

El problema radica cuando la instalo en otro equipo con winxp... instalo firebird 2.1 y en la carpeta de UDF agrego la dll que he creado que funciona en mi maquina, genero la consulta y me muestra el siguiente error:

Cita:
Invalid Token
Invalid request BLR at offset 707.
Function MI_FUNCION is not defined.
Module name or entrypoint could not be found.
Alguien puede ayudarme a solucionar este problema.
Responder Con Cita
  #2  
Antiguo 09-03-2010
Avatar de jhonny
jhonny jhonny is offline
Jhonny Suárez
 
Registrado: may 2003
Ubicación: Colombia
Posts: 7.058
Poder: 29
jhonny Va camino a la famajhonny Va camino a la fama
Aún no declaras la función en la base de datos
__________________
Lecciones de mi Madre. Tema: modificación del comportamiento, "Pará de actuar como tu padre!"

http://www.purodelphi.com/
http://www.nosolodelphi.com/
Responder Con Cita
  #3  
Antiguo 09-03-2010
subzero subzero is offline
No confirmado
 
Registrado: ene 2004
Ubicación: Móntería - Córdoba - Colombia
Posts: 289
Poder: 0
subzero Va por buen camino
Creo que si la tengo declara es más ejecuto el siguiente script

Código SQL [-]
DECLARE EXTERNAL FUNCTION ECUACION
  DECIMAL(18, 4),
  DECIMAL(18, 4),
  DECIMAL(18, 4),
  DECIMAL(18, 4),
  DECIMAL(18, 4),
  DECIMAL(18, 4),
  DECIMAL(18, 4)
RETURNS DECIMAL(18, 4) BY VALUE
ENTRY_POINT 'ecuacion' MODULE_NAME 'MIS_UDFS';

Para más info anexo el codigo de la dll hecha en delphi:

Código Delphi [-]
library MIS_UDFS;

uses
  SysUtils,
  Classes;

function ecuacion(var cant, bonif, costo, desc, desc2, desc3, present : real) : Real;stdcall;
var dt1, dt2, dt3, costo_dts : real;
begin
  dt1 := 0; dt2  := 0; dt3  := 0; costo_dts  := 0;
  dt1       := Costo * (desc/100);
  costo_dts := Costo - dt1;
  dt2       := costo_dts * (desc2/100);
  costo_dts := costo_dts - dt2;
  dt3       := costo_dts * (desc3/100);
  costo_dts := costo_dts - dt3;
  costo_dts := (costo_dts * cant)/(cant + bonif);
  result := costo_dts / Present;
end;

exports ecuacion;

begin
end.
Responder Con Cita
  #4  
Antiguo 09-03-2010
Avatar de mightydragonlor
[mightydragonlor] mightydragonlor is offline
Miembro Premium
 
Registrado: feb 2007
Ubicación: Medellín-Colombia
Posts: 587
Poder: 18
mightydragonlor Va por buen camino
las udf deben declararse en cada maquina que las vaya a usar, no estoy seguro, pero creo que la udf va vinculada al motor y no a la base de datos.
__________________
mas confundido que Garavito el día del Niño.
Responder Con Cita
  #5  
Antiguo 09-03-2010
Avatar de guillotmarc
guillotmarc guillotmarc is offline
Miembro
 
Registrado: may 2003
Ubicación: Huelva
Posts: 2.638
Poder: 23
guillotmarc Va por buen camino
El mensaje de error es, como dice Jhonny, de que no está declarada. Pero está claro que si ejecutas ese script entonces debería estarlo. Así que no se me ocurre donde está el error. Si en un Servidor Firebird te funciona, en otro también debería hacerlo.

Yo te sugiero de que no te compliques la vida con UDF's (que siempre es un problema a la hora de distribuir la aplicación) y que utilices un procedimiento almacenado.

donde ahora tienes algo como :

select idventa, ..., ecuacion(cantidad, bonif, costo, ...)
from XXX

ahora puedes hacer :

select idventa, ..., (select RESULTADO from ECUACION(cantidad, bonif, costo, ...))
from XXX

Ya solo tienes que programar el procedimiento almacenado ECUACION para que haga el mismo cálculo que tu Dll.

NOTA: no te olvides poner un SUSPEND; al final del procedimiento almacenado. Ya que el resultado tiene que devolverse como un Dataset para que sea leído en la subconsulta donde se va a utilizar.

Saludos.
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no).

Última edición por guillotmarc fecha: 09-03-2010 a las 19:49:19.
Responder Con Cita
  #6  
Antiguo 09-03-2010
Avatar de jhonny
jhonny jhonny is offline
Jhonny Suárez
 
Registrado: may 2003
Ubicación: Colombia
Posts: 7.058
Poder: 29
jhonny Va camino a la famajhonny Va camino a la fama
Cita:
Empezado por guillotmarc Ver Mensaje
El mensaje de error es, como dice Jhonny, de que no está declarada. Pero está claro que si ejecutas ese script entonces debería estarlo. Así que no se me ocurre donde está el error. Si en un Servidor Firebird te funciona, en otro también debería hacerlo.
En ese caso, a mi se me acurre que si dicho Script esta siendo ejecutado con IBExpert, FlameRobin o similares... quizá lo estas ejecutando pero se te haya olvidado hacer el commit... bueno, es lo que se me ocurre de momento :S.
__________________
Lecciones de mi Madre. Tema: modificación del comportamiento, "Pará de actuar como tu padre!"

http://www.purodelphi.com/
http://www.nosolodelphi.com/
Responder Con Cita
  #7  
Antiguo 09-03-2010
subzero subzero is offline
No confirmado
 
Registrado: ene 2004
Ubicación: Móntería - Córdoba - Colombia
Posts: 289
Poder: 0
subzero Va por buen camino
Efectivamente realize pruebas con la ecuacion en un procedimiento almacenado y definitivamente menos dolores de cabeza... le agradezco a todos por su aporte, especialmente a guillotmarc, pués aprendí una utilidad diferente para con los procedimientos almacenados.
Responder Con Cita
  #8  
Antiguo 10-03-2010
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.038
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
¿Desde qué versión es posible hacer eso?, no recuerdo haber hecho uso de esa particularidad.
Responder Con Cita
  #9  
Antiguo 10-03-2010
Avatar de guillotmarc
guillotmarc guillotmarc is offline
Miembro
 
Registrado: may 2003
Ubicación: Huelva
Posts: 2.638
Poder: 23
guillotmarc Va por buen camino
Hola Casimiro.

Que yo sepa ha sido posible hacerlo desde siempre, desde Firebird 1 (que es cuando empecé a utilizar Interbase/Firebird). Que yo recuerde, en los procedimientos almacenados siempre se ha podido añadir el suspend (que normalmente utilizas con un for select) para que devuelva el resultado como un dataset.

Aunque esto normalmente se usa para leer un dataset en tu programa (en lugar de utilizando un select), también puedes utilizar el procedimiento almacenado dentro de un select, en una union, en una subconsulta, etc. ...

Así que un buen día me di cuenta de que eso podia ser muy útil, ya que además de utilizarlo para consultar datos también podría servir para definirme mi propia librería de funciones en PSQL, y no tener que depender tanto de udf's externas.

La verdad es que desde entonces lo vengo usando de forma masiva.

Me es especialmente imprescindible cuando tengo que importar datos. Muchas veces tengo que programar importaciones hacia nuestro sistema de las gestiones que puedan tener nuevos clientes. Con lo que te encuentras que tienes que trabajar con todo tipo de datos, y que muchas veces los clientes lo tiene en un simple campo de texto, mal formateado, y que te las tienes que apañar para convertirlo, por ejemplo, en un timestamp.

Por eso tengo una librería de funciones como esta (en este caso intenta convertir una cadena en fecha) :

Código SQL [-]
CREATE PROCEDURE "X_IMPORT_Data" (
    VALOR VARCHAR(50))
RETURNS (
    DATA TIMESTAMP)
AS
DECLARE VARIABLE DIA INTEGER;
DECLARE VARIABLE MES INTEGER;
DECLARE VARIABLE ANO INTEGER;
DECLARE VARIABLE I INTEGER;
DECLARE VARIABLE TMP VARCHAR(50);
begin
  DATA = null;
  I = 1;
  while (substring(:VALOR from I for 1) not in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')) do begin
    I = I + 1;
  end
  TMP = '';
  while (substring(:VALOR from I for 1) in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')) do begin
    TMP = TMP || substring(VALOR from I for 1);
    I = I + 1;
  end
  DIA = cast(TMP as integer);
  while (substring(:VALOR from I for 1) not in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')) do begin
    I = I + 1;
  end
  TMP = '';
  while (substring(:VALOR from I for 1) in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')) do begin
    TMP = TMP || substring(VALOR from I for 1);
    I = I + 1;
  end
  MES = cast(TMP as integer);
  while (substring(:VALOR from I for 1) not in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')) do begin
    I = I + 1;
  end
  TMP = '';
  while (substring(:VALOR from I for 1) in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')) do begin
    TMP = TMP || substring(VALOR from I for 1);
    I = I + 1;
  end
  ANO = cast(TMP as integer);
  if (:ANO < 20) then ANO = 2000 + ANO;              /* Tracto l'any, ja que pot estar en 2 digits */
  else if (:ANO < 100) then ANO = 1900 + ANO;
  TMP = cast(MES as varchar(20)) || '-' || cast(DIA as varchar(20)) || '-' || cast(ANO as varchar(20));
  DATA = cast(TMP as TIMESTAMP);
  suspend;
  when any do exit;    /* En cas d'Error retorno Null */
end
^

Creo una tablas temporales de importacion, con la estructura de los datos a importar, y hago un DataPump, con lo que ya tengo todos los datos en una única base de datos Firebird.

Luego ya solo tengo que hacer los correspondentes INSERT INTO *** SELECT **** FROM IMPORT_**** para poner los datos de las tablas temporales en las tables correspondientes de nuestro sistema, y puedo utilizar esas funciones como si fueran UDF's, con lo que he recortado drasticamente el tiempo que tardo en hacer una importacion de datos (antes me tenía que hacer un programa en Delphi ex-profeso en cada ocasión).

Saludos
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no).

Última edición por guillotmarc fecha: 10-03-2010 a las 19:50:29.
Responder Con Cita
  #10  
Antiguo 10-03-2010
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.038
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Gracias por la aclaración, guillotmarc , aunque realmente estaba preguntando por lo de añadir un procedimiento almacenado en un select, por ejemplo: "select * from PA_ArticulosRecibidosCompras(100)"
Pero releyendo lo escrito me he dado cuenta que he dicho una tontería, últimamente ando bastante "disperso" y cometiendo errores sinsentido.
No sé, será la edad o que necesito unas vacaciones de varios años (pagadas, por supuesto)
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

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Firebird 1.5.4 funciona en Win Vista pero Firebird 2.0.1 NO !!! Hagen Firebird e Interbase 5 19-05-2007 21:17:54
Firebird 1.5.3 Error:No puede ejecutarse Firebird Guardian xq ya hay una instancia Delphius Firebird e Interbase 5 26-01-2007 10:19:20
alguien ha utilizado Firebird DDX provider? (conectarse con db en firebird!) JuanErasmo .NET 1 04-11-2006 16:17:12
Firebird : Llamado para probadores de Firebird 2.0 JOSEPE Firebird e Interbase 0 12-03-2005 20:33:18
Problemas Firebird Super Server 1.5 con RFunc Firebird v 1.0 Prophoenix Firebird e Interbase 1 09-03-2004 11:40:48


La franja horaria es GMT +2. Ahora son las 01:26:36.


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