Este apartado es una pequeña guía práctica de portabilidad de aplicaciones construidas con MultiBase en entornos con CTSQL a entornos con servidor Oracle versiones 6 a 10.
A) Tipos de datos:
Las conversiones entre los tipos de datos del CTSQL de MultiBase y los
del servidor de base de datos de Oracle se
realizan de forma automática según se indica en las siguientes
tablas:
| CTSQL | Oracle |
| Si es versión 6 y «size < 256»: | |
| CHAR(size) | CHAR(size) |
| Si es versión 7 y «size < 2000»: | |
| CHAR(size) | VARCHAR2 |
| Si es versión 6 y «size > 255» o versión 7 y «size > 2000»: |
|
| CHAR(size) SMALLINT INTEGER DECIMAL(p,s) MONEY(p,s) SERIAL DATE TIME ROWID |
LONG SMALLINT INTEGER DECIMAL(p,s) DECIMAL(p,s) INTEGER DATE CHAR(11) ROWID |
| Oracle | CTSQL |
| NUMBER(p) | INTEGER |
| NUMBER(p) | SMALLINT |
| NUMBER(p,s) | DECIMAL(p,s) |
| NUMBER(p,s) | MONEY(p,s) |
| CHAR(size) | CHAR(size) |
| VARCHAR2 | CHAR(size) |
| LONG | CHAR(DBLONGCHAR) |
| DATE (sin TIME) | DATE |
DBLONGCHAR es la variable de configuración que limita la longitud del LONG para su manejo en programas MultiBase.
El programador tendrá que tener en cuenta estas tablas si quiere actualizar el catálogo de MultiWay con una base de datos ya existente en Oracle, creando un esquema acorde con las conversiones automáticas que realiza el «gateway» (ver «Casos Prácticos» al final de este documento).
B) Funciones:
Restricciones de funcionalidad:
Con la versión 6 del gestor de Oracle no se pueden utilizar las funciones contempladas por MultiBase en frases SQL (consulte el epígrafe 2.3 del Manual del SQL de MultiBase), al no existir equivalencia de las mismas en dicho gestor ni posibilidad de generarlas.
Por el contrario, la versión 7 del gestor de Oracle sí permite la creación de funciones SQL (previa instalación de la utilidad correspondiente de Oracle) que se almacenan en la misma base de datos. En este momento, y siguiendo este procedimiento, MultiWay sólo crea la función «typelength» de forma automática, siempre y cuando la variable ORACLE_PROC se encuentre activada. El resto podrían ser simuladas sin dificultad siguiendo el mismo mecanismo.
Por lo que respecta a las funciones SQL propias de Oracle, éstas podrán utilzarse si se especifican adecuadamente en la sección «.FUNCTIONS» del fichero de configuración «gworacle.env».
C) Instrucciones:
—Primera fase de traducción:
Algunas de las diferencias sintácticas existentes en instrucciones
del CTSQL respecto a las del servidor de Oracle se
resuelven por el «gateway» de forma transparente al programador
en una primera fase de traducción. Por ejemplo:
Las fases subsiguientes resuelven, de manera particularizada, más diferencias de este tipo, así como el resto de incompatibilidades existentes entre las instrucciones del CTSQL de MultiBase y las del servidor de Oracle.
—CREATE DATABASE, DROP DATABASE, START DATABASE y DATABASE.
Estas instrucciones suponen la ejecución automática por
parte del «gateway» de los siguientes pasos:
| CREATE DATABASE | -> | CONNECT + CREATE MULTIBASE CATALOGS |
| DROP DATABASE | -> | DISCONNECT + DROP MULTIBASE CATALOGS |
| START DATABASE | -> | CONNECT |
| DATABASE | -> | CONNECT |
Siendo CREATE MULTIBASE CATALOGS y DROP MULTIBASE CATALOGS instrucciones nuevas de MultiWay (disponibles para el programador), y CONNECT y DISCONNECT instrucciones internas para el gestor de Oracle.
Como puede observarse, la creación como tal de la base de datos ha de realizarse previamente a través del administrador de Oracle.
Cada una de las instrucciones anteriores asigna a la variable de entorno ORACLE_SID el nombre de la base de datos de conexión (considerando los posibles valores de la variable de configuración DBSYN existente en «gworacle.env»). El «usuario/password» al que se conecta viene determinado por la variable de entorno ORACLE_UID (definida en el entorno o en «gworacle.env»).
NOTA al programador: El cambio de base de datos de MultiBase tiene su equivalente frente a Oracle en las siguientes instrucciones dentro de un programa CTL:
close database <oldbname>
call putenv ("ORACLE_UID",<valor>,1)
database <newdbname>;
Siendo «oldbname» y «newdbname» los nombres de las bases de datos de Oracle (ORACLE_SID) o sinónimos de las mismas, en cuyo caso deberán figurar como tal («DBSYN:dbsynonym=dbname») en el fichero de configuración «gworacle.env». Por su parte, «valor» es el nuevo «usuario/password» (variable de entorno ORACLE_UID del entorno de usuario o del fichero «gworacle.env») al que se cambia.
—CREATE TABLE.
Frente a la versión 6 del gestor de Oracle:
El atributo NOT NULL se mantiene directamente por el SQL de Oracle.
La claúsula «PRIMARY KEY» se simula de forma automática por el «gateway» a través de la creación de un índice único sobre las columnas especificadas y cuyo identificador es el nombre de la tabla precedido por «PK».
El atributo DEFAULT es simulado también por el «gateway» en las operaciones de INSERT cuyos valores en «VALUES» se introduzcan a través de constantes o variables «hosts» (esto se hace extensivo al FORM).
Restricciones de funcionalidad:
Respecto al atributo DEFAULT, la simulación no funciona cuando los valores se introducen a través de una instrucción SELECT, ya que no puede controlarse su resultado («INSERT… SELECT…»).
El resto de atributos (entre ellos CHECK) y la clave referencial se aceptan gramaticalmente, pero no funcionan a nivel de SQL.
No obstante, la definición de cualquier atributo queda almacenada en los catálogos de MultiBase, con lo que, al nivel de programa (FORM), muchos de ellos siguen teniendo validez (RIGHT, ZEROFILL, etc.), ya que se utiliza esta información como base.
Frente a la versión 7 del gestor de Oracle:
El SQL mantiene directamente los atributos CHECK y DEFAULT, además de NOT NULL. También las claúsulas PRIMARY KEY y FOREIGN KEY son manejadas automáticamente, con lo que el «gateway» ya no tiene que realizar ninguna labor de simulación para ellas.
Restricción de funcionalidad: El resto de atributos no funcionan al nivel de SQL.
—CREATE TEMP TABLE.
El empleo y manejo de tablas temporales desde programas CTL no varía
a pesar de que internamente son tablas normales de usuario (y no temporales)
identificadas con el número de proceso y el prefijo «MBT».
Dado que en Oracle no existe este tipo
de tablas, éstas son simuladas automáticamente por el «gateway»,
resultando invisible al programador esta carencia. Y lo mismo sucede
con la tabla temporal de la instrucción «SELECT… INTO
TEMP…».
NOTA al programador: Si a lo largo de la ejecución se ha cambiado sucesivamente de base de datos, puede que al finalizar el proceso se hayan creado tablas temporales en diferentes usuarios Oracle. En estos casos, el «gateway» las borrará naturalmente para simular esta «temporalidad», pero haciendo dos supuestos a la hora de conectarse a los usuarios: Que no se haya cambiado de ORACLE_SID y que la «password» de estos usuarios coincida con su nombre. En cualquier otro caso quedarían tablas sin borrar.
—CREATE INDEX.
Restricción de funcionalidad: El atributo «DESC» no
es efectivo, ya que los índices son siempre ascendentes.
NOTAS al programador:
Las tablas y los índices han de tener identificadores distintos, dado que así lo exige Oracle, y 18 caracteres como máximo (límite de CTSQL).
Si la base de datos existía en Oracle con anterioridad a su manejo con MultiWay, puede suceder que haya identificadores que superen esa longitud de 18 caracteres. El problema se soluciona fácilmente creando sinónimos en Oracle para todos esos identificadores con la longitud admitida por CTSQL. Estos nombres serán los que se manejen desde programas CTL.
Si al ejecutar una frase SQL que genera, modifica o borra un objeto de la base de datos se produce un error actualizando el catálogo de MultiBase, éste puede quedar inconsistente, ya que la acción sobre el objeto no se deshace. En este caso es necesario rectificarlo para que cualquier aplicación MultiBase funcione correctamente.
—ALTER TABLE.
Dado que esta instrucción es desconocida por el SQL de Oracle,
el «gateway» la simula para que, de forma transparente, el
programador pueda seguir usándola.
Como información, esta instrucción supone internamente la ejecución de los pasos que se indican a continuación:
CREATE TEMP TABLE <newtable> (instrucción
simulada a su vez)
INSERT INTO <newtable> SELECT FROM <oldtable>
DROP TABLE <oldtable>
RENAME TABLE <newtable> TO <oldtable>
CREATE INDEX ON… (los índices que tuviera la tabla)
—RENAME COLUMN.
No funciona en esta versión.
—GRANT CONNECT.
La sintaxis de esta instrucción en Oracle difiere
de la del CTSQL. Para evitar esta incompatibilidad, el «gateway» añade
al final de la misma la cláusula «IDENTIFIED BY»,
y como «password» sigue el criterio de utilizar el mismo
identificador empleado en el nombre de usuario.
—GRANT SELECT.
No funciona la opción «GRANT SELECT (<columna1>... <columnan>)…»,
sino únicamente «GRANT SELECT…», sin especificación
de columnas.
—INSERT.
La inserción automática para el tipo de dato SERIAL (inexistente
en Oracle) se simula en parte gracias
a una tabla creada a tal efecto («MBSERIAL»), de donde el «gateway» lee
el último valor que asignó de esta forma (por cada tabla
con una columna de este tipo, existe una fila con dicho valor).
—FETCH CURSOR.
Restricciones de funcionalidad:
En MultiBase, todos los «cursores» permiten el acceso a las filas siguiente, anterior, primera y última (NEXT, PREVIOUS, FIRST, LAST).
Aunque Oracle no tiene «cursores SCROLL», el «gateway» hace que esto se siga cumpliendo de forma transparente al programador, pero restringiéndolo a los «cursores» que no sean «FOR UPDATE». Para ello emplea un fichero secuencial («SCRnnnnpid.GW») donde realiza el «scroll» necesario de los registros seleccionados.
—LOCK TABLE.
La instrucción LOCK TABLE será capaz de bloquear una tabla
si la variable de configuración MBCOMMIT tiene el valor «OFF» (en
el fichero «gworacle.env»), ya que este «COMMIT» automático
después de cada instrucción SQL desbloquea las tablas cuando
MultiBase funciona frente al SQL de Oracle.
Lo normal es encerrar esta instrucción dentro de una transacción
controlada por el programador, de manera que cuando se quiera desbloquear
de verdad se finalice la transacción con «COMMIT».
—OPEN CURSOR.
Los identificadores de CURSOR tendrán como máximo 15 caracteres en lugar de 18 (máximo permitido por CTSQL para cualquier identificador de la base de datos frente a cualquier SQL). Esta restricción permite distinguir «cursores» con igual nombre en diferentes módulos CTL, aspecto éste que sólo sabe manejar el CTSQL.
Si el CURSOR tiene la cláusula «FOR UPDATE», el comportamiento de esta instrucción es algo diferente frente al servidor de Oracle:
Este SQL ejecuta la frase SELECT en el momento de abrir el CURSOR, bloqueando todas las filas obtenidas en la selección hasta el «COMMIT» de la transacción que la incluye.
Si el usuario no controla las transacciones desde su programa, es la variable de configuración «MBCOMMIT=ON» (del fichero «gworacle.env») la que puede provocar este «COMMIT».
Tanto en un caso como en otro, es necesario cerrar previamente el CURSOR, ya que el «COMMIT» sólo es enviado al SQL de Oracle por el «gateway», si no existe ningún CURSOR abierto «FOR UPDATE».
Si al abrir el CURSOR Oracle encuentra problemas para bloquear todas las filas seleccionadas, el CURSOR permanecerá cerrado. La ejecución del programa CTL sigue su curso siempre y cuando el CURSOR haya sido definido «FOR UPDATE… NOWAIT», quedando registrado este incidente en la variable «locked», que tomará el valor «TRUE». Esto implica que para que un programa CTL se comporte de manera equivalente cuando funcione frente al servidor de Oracle es necesario controlar también en el «OPEN» los problemas de interbloqueo de «cursores», y no sólo en el «FETCH», como sucede en MultiBase con CTSQL.
—SELECT… FROM…
NOTA al programador: El «gateway» está simulando el
comportamiento de CTSQL en un «SELECT {MIN,MAX,AVG,SUM}» sin «GROUP
BY» (ya que Oracle devuelve una
fila con valor «NULL» si el número de filas seleccionadas
es cero, mientras que CTSQL no devuelve nada), con la salvedad de que
el programador no puede distinguir el caso de una selección de
filas con valores nulos (aunque esto no es habitual).
Restricciones de funcionalidad:
La restricción «DISTINCT/UNIQUE» NO se puede incluir junto con la cláusula «FOR UPDATE».
NO se puede emplear el «outer» en la cláusula «FROM». El «gateway» no realiza la traducción debido a la falta de equivalencia con el «outer» definido por columnas de Oracle.
NO se pueden utilizar alias en las cláusulas «ORDER BY» y «GROUP BY». La solución para aquellos casos en que sea necesario su empleo (referencias a columnas compuestas: expresiones, agregados, etc.) es utilizar en su lugar los números de orden dentro de la lista de campos de la SELECT.
—ROLLFORWARD DATABASE y UPDATE STATISTICS.
Al no tener equivalencia en Oracle, estas
instrucciones no son enviadas a su SQL por el «gateway»,
con lo que sus efectos son nulos aunque se utilicen en programas CTL,
favoreciendo de esta manera la compatibilidad de fuentes frente a distintos
servidores de bases de datos.
—UNLOCK TABLE.
Esta instrucción es ignorada por el «gateway», ya
que Oracle no la contempla. Para conseguir
el desbloqueo de una tabla ha de realizarse un «COMMIT» de
la transacción dentro de la cual se hizo el bloqueo (para más
información vea lo comentado anteriormente para la instrucción
LOCK TABLE).
D) Otros:
—Tablas compartidas: Para compartir una tabla entre dos bases de datos (dos
usuarios Oracle) se sigue un camino similar al
realizado frente al gestor CTSQL.
El usuario A, creador de la tabla a compartir, da los permisos que considere oportunos al usuario B sobre la misma y sobre la tabla «mbserial» si existe algún campo cuyo tipo de dato es SERIAL.
Para poder utilizar el mismo nombre de tabla, el usuario B crea el sinónimo:
CREATE SYNONYM nombre_de_tabla
FOR usuario_A.nombre_de_tabla
Además, crea la tabla en modo mantenimiento para que su catálogo la contenga y, con una instrucción UPDATE, modifica el campo «dirpath» de la fila que haya aparecido en «mbtables» para esa tabla, cambiando el valor «usuarioB» por «usuarioA» (es en A donde realmente se halla la tabla).
Si en algún momento se altera la estructura de la tabla hay que repetir el procedimiento anterior (ALTER en modo mantenimiento y cambio de «dirpath»).
—Catálogo de MultiBase: Es posible romper la relación «biunívoca» existente entre bases de datos MultiBase y usuarios Oracle.
Si se quiere hacer corresponder una base de datos MultiBase con varios usuarios Oracle manteniendo un solo catálogo, éstos tendrían que compartir las tablas «mb*» siguiendo el procedimiento anterior. Uno de los usuarios sería el creador real del catálogo («dador» de permisos) y los demás compartirían las tablas (creando sinónimos).
La tabla «mbserial» no aparece en el catálogo, dada su naturaleza interna, pero sí han de poder manipularla todos, para lo cual, además de los permisos:
EXECSQL GRANT ALL PRIVILEGES ON mbserial TO PUBLIC
cada uno de los usuarios, excepto el creador del catálogo, necesita el siguiente sinónimo:
EXECSQL CREATE SYNONYM mbserial
FOR usuario_creador.mbserial
Este procedimiento podría seguirse también con las tablas del entorno de programación (tablas «ep*») si así se desea.