domingo, 30 de enero de 2011

Servicios Heterogeneos

El mecanismo para conectar una fuente de datos oracle con una fuente de datos no oracle, como por ejemplo MSQLServer, MSAccess, mysql, ha sido denominado por Oracle como Servicios heterogéneos de conectividad o Heterogeneus Services (en Inglés), y que básicamente se puede entender como una conexion a otras fuentes de datos a través de los enlaces llamados database links.
Entre los objetivos más importantes de los servicios heterogéneos se encuentran:
- Usar el SQL de oracle para accesar datos de otras fuentes no oracle, como si estuvieran en el servidor Oracle.
- Hacer llamadas a otros servicios, APIS, fuentes de datos de manera transparente desde su ambiente distribuído.
Configurar dicha conexión es una tarea muy sencilla, solo basta tener instalados los respectivos drivers y modificar algunos archivos del servidor Oracle. Veamos cómo crear una conexión con una base de datos MSAccess a través de un ODBC
1. Configurar el ODBC. (supongo que esto ya lo sabes hacer, entonces no me extenderé en eso). Asumamos que el nombre al la conexión ODBC se llama extbd, nombre que usaremos de ahora en adelante.
2. Ahora bien, creamos un archivo que se llamará init.ora, es decir, para nuestro caso nuestra bd remota la vamos a llamar extbd, por lo cual el nuestro archivo se llamará initextbd.ora y lo guardamos en el directorio ORACLE_HOME\hs\admin, donde ORACLE_HOME es el directorio de instalación de Oracle en la máquina, en mi caso es C:\oracle\ora10g\10.1.0\Db_1
Bien, dentro de este archivo vamos a configurar el valor para el parámetro HS_FDS_CONNECT_INFO asignándole el nombre del odbc que fué creado . Para nuestro ejemplo sería:

-------------------------------------------------------------
# This is a sample agent init file that contains the HS parameters that are
# needed for an ODBC Agent.
#
# HS init parameters
#
HS_FDS_CONNECT_INFO = extbd
HS_FDS_TRACE_LEVEL = OFF
#
# Environment variables required for the non-Oracle system
#
#set =
--------------------------------------------------------------

3. El siguiente paso consiste en modificar el archivo listener.ora del servidor Oracle, agregando algunas entradas:
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = C:\oracle\ora10g\10.1.0\Db_1)
(PROGRAM = extproc)
)
(SID_DESC =
(SID_NAME = extbd)
(ORACLE_HOME = C:\oracle\ora10g\10.1.0\Db_1)
(PROGRAM = hsodbc)
)
)
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = )(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = )(PORT = 1524))
)
)
)
Reiniciar el listener. Para ello, atraves de la consola del Sistema operativo
Lsnrctl stop
Lsnrctl start
4. Agregar la entrada para la fuente de datos no Oracle en el archivo tnsnames.ora
extbd =
(DESCRIPTION=
(ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1524))
(CONNECT_DATA=(SID=extbd))
(HS=OK)
)
donde,
HS=OK indica que se usarán servicios heterogéneos
5. Crear el enlace database link desde oracle referenciando el servicio heterogéneo:
Create public database link ext.world connect to admin identified by admin using 'extbd';
Listo, ahora puedes verificar la connexion a la bd externa lanzando una query
SELECT * from latabladelafuenteexterna@ext.world;
__________________________________________________________________________________
"Te quiero. Te quise desde el primer momento en que te vi. Te quise incluso antes de verte por primera vez."
Un lugar en el Sol

jueves, 27 de enero de 2011

Condición de Compilación Oracle 10g

En PL/SQL, y por lo general cualquier lenguaje, cada nueva versión llega con características interesantes, que merecen implementarse. En muchas ocasiones esto implica tener que eliminar código viejo y reemplazarlo por las funcionalidades nuevas. Pues bien, una de estas características, y que surgió con la versión 10g, es la de permitir personalizar una aplicación PL/SQL sin tener que remover código fuente, esto es permitir evaluar la versión con la que se esta trabajando y dependiendo de la versión, utilizar el código de programación más acorde, a esto se le conoce como condición de compilación.

Veamos un ejemplo, el siguiente código

-- Utilizamos la constante ver_le_10_2, expresión estática requisito
-- para ser evaluada en una cóndición de compilación.
-- Esta constante retorna verdadero si la versión es menor o igual
-- a 10 y el release menor o igual a 2


$IF dbms_db_version.ver_le_10_2 $THEN
SELECT CASE p_tipoSECUENCIA
WHEN 'DATOS' THEN sec_datos.nextval
WHEN 'ADMIN' THEN sec_admin.nextval
END
INTO v_secuencia
FROM dual;
$ELSE
v_secuencia :=
CASE p_tipoSECUENCIA
WHEN 'DATOS' THEN sec_datos.nextval
WHEN 'ADMIN' THEN sec_admin.nextval
END;
$END

La condición de compilación en ORACLE se implementa cuando utilizamos una condición de compilación, podemos identificarla cuando al realizar la condición IF, anteponemos el símbolo "$", en este caso:

$IF dbms_db_version.ver_le_10_2 $THEN esto significa que si encuentra una versión anterior o igual a la 10.2 tendrá en cuenta el código correspondiente:

SELECT CASE p_tipoSECUENCIA
WHEN 'DATOS' THEN sec_datos.nextval
WHEN 'ADMIN' THEN sec_admin.nextval
END
INTO v_secuencia
FROM dual;

De lo contrario $ELSE

v_secuencia :=
CASE p_tipoSECUENCIA
WHEN 'DATOS' THEN sec_datos.nextval
WHEN 'ADMIN' THEN sec_admin.nextval
END;

Oracle en tiempo de compilación, tomará el código que se ajuste a la versión current de base de datos. Esto no solamente dará transportabilidad de código a diferentes versiones, sino que estimula a que nosotros como programadores estemos al tanto de las nuevas características y las implementemos de una manera sencilla.

__________________________________________________________________________________
"Cuando tita sintió sobre sus hombros la ardiente mirada de Pedro, comprendió perfectamente lo que debe sentir la masa de un buñuelo al entrar en contacto con el aceite hirviendo: Era tan real la sensación de calor que la invadía, que ante el temor de que como a un buñuelo le empezaran a brotar burbujas por todo el cuerpo, el vientre, el corazón, los senos, bajó la mirada y trató de huir."
Como agua para chocolate

domingo, 16 de enero de 2011

Herencia con oracle 10g

Con Oracle 8, el entusiasmó de los objetos duró poco cuando comprobé que los TYPE OBJECT no soportaban la herencia y por supuesto el polimorfismo, realicé todo un trabajo embebiendo objetos padre dentro del hijo, de esta manera pude emular esta característica.

Acabo de realizar una reingeniería de mi proyecto, utilizando la verdadera herencia que esta versión ofrece (10g) y quiero compartir una de las características más importantes que pude utilizar, el polimorfismo.

Lo que encontraremos en esta entrada es un sencillo ejemplo de herencia, representado por tres objetos: padre, hijo1 e hijo2.

El type padre declara 3 atributos:
  • atributo1
  • atributo2
  • atributo3
Y declara dos métodos (no los implementa):
  • SetAtributo
  • Listar
Nuestros types hijos: hijo1, hijo2, cada uno mantendrá un atributo "propio":

El type hijo1 tiene 1 atributo propio (este type-clase hereda de padre)
  • ahijo1
E implementamos los métodos :
  • SetAtributo
  • Listar
El type hijo2 tiene 1 atributo propio (este type-clase hereda de padre)
  • ahijo2
E implementamos los métodos :
  • SetAtributo
  • Listar
Por favor observemos bien la implementación, que realiza cada tipo de método.

El código:

/* Declaración del TYPE padre, este tipo se crea con la característica NOT FINAL, para permitir ser utilizado como "padre" por otros types.

Tener en cuenta que los métodos no son implementados. */

CREATE OR REPLACE TYPE PADRE AS OBJECT (
atributo1 number(5),
atributo2 varchar2(10),
atributo3 date,
member procedure SetAtributo,
member procedure Listar
) not final
/

/* Creación de los tipos HIJO 1, HIJO 2. Estos TYPE heredan del tipo PADRE (UNDER PADRE). Cada tipo conserva un atributo propio (ahijo1, ahijo2), y lo más importante implementan los métodos SetAtributo y Listar. */

CREATE OR REPLACE TYPE HIJO1 UNDER PADRE (
ahijo1 number(5),
overriding member procedure SetAtributo,
overriding member procedure Listar,
member procedure Set1
)
/

CREATE OR REPLACE TYPE BODY HIJO1 IS

OVERRIDING MEMBER procedure SetAtributo IS
BEGIN
atributo1 := 1000;
atributo2 := 'HIJO 1';
atributo3 := sysdate-1000;
ahijo1 := 1553;
set1;
END SetAtributo;

OVERRIDING MEMBER procedure Listar IS
BEGIN
dbms_output.put_line(' Atributo 1 --> 'SELF.atributo1);
dbms_output.put_line(' Atributo 2--> 'SELF.atributo2);
dbms_output.put_line(' Por HIJO1 'SELF.ahijo1);
END Listar;

MEMBER procedure Set1 IS
BEGIN
atributo1 := 4567;
END Set1;

END;
/

CREATE OR REPLACE TYPE HIJO2 UNDER PADRE (
ahijo2 number(5),
overriding member procedure SetAtributo ,
overriding member procedure Listar
)
/

CREATE OR REPLACE TYPE BODY HIJO2 IS

OVERRIDING MEMBER procedure SetAtributo IS
BEGIN
atributo1 := 2000;
atributo2 := 'HIJO 2';
atributo3 := sysdate-2000;
ahijo2 := 9999;
END SetAtributo;

OVERRIDING MEMBER procedure Listar IS
BEGIN
dbms_output.put_line(' Atributo 1 --> 'SELF.atributo1);
dbms_output.put_line(' Atributo 2--> 'SELF.atributo2);
dbms_output.put_line(' Por HIJO2 'SELF.ahijo2);
END Listar;

END;
/

Fin del código que crea los tipos.

Veamos ahora el código para probar el polimorfismo

declare
v_padre padre;
v_hijo1 hijo1;
v_hijo2 hijo2;
begin
-- Inicializamos los hijos (hijo1, hijo2)
v_hijo1 := new hijo1(null,null,null,null);
v_hijo1.SetAtributo;
v_hijo2 := new hijo2(null,null,null,null);
v_hijo2.SetAtributo;

-- Instanciamos el padre con cada hijo y listamos valores.
v_padre := v_hijo1;
v_padre.Listar;
v_padre := v_hijo2;
v_padre.Listar;
end;

Quiero que antes de ejecutarlo, observemos bien el papel de este código:
  1. Se inicializan los objetos hijos, es decir, realizamos el llamado de los métodos SetAtributo tanto del hijo1 como del hijo2.
  2. Se Instancia al padre con el valor de cada objeto hijo, si señor, con el valor de cada objeto hijo, de esta manera este padre podra resolver los métodos de cada uno de sus hijos
Ejecutemos este ejemplo, una salida:

SQL> start probarpoli
Atributo 1 --> 4567 Atributo 2-->HIJO 1 Por HIJO1 Propio 1553
Atributo 1 --> 2000 Atributo 2-->HIJO 2 Por HIJO2 Propio 9999

Procedimiento PL/SQL terminado correctamente.

Quiero que detallen la forma en que podríamos encapsular el comportamiento de los métodos hijos, si son buenos observadores, se darán cuenta que estamos manipulando, desde el padre, atributos que pertenecen a diferentes hijos.
Bueno, este ejemplo aunque sencillo, muestra lo robusto que puede ser nuestro código con este paradigma asumido por PL/SQL.
__________________________________________________________________________________
"Llegar a viejo sin haberse enamorado de verdad..., es como no haber vivido"
Conoces a Joe Black