Página de inicio - Tecla de acceso: 1
Notas técnicas

MultiBase. Notas a la versión 3.0, release 00

1. Mejoras incorporadas

La versión 3.0 de MultiBase añade nuevas funcionalidades y prestaciones al producto. Especialmente significativas resultan las mejoras introducidas en la versión para Windows, que ahora incorpora el generador de informes EasyReport (disponible ya en UNIX y MS-DOS desde la versión 2.0.05), un nuevo editor «Wedit» y el comando ctlinf.

1.1. EasyReport

Esta herramienta emplea la documentación interactiva dentro del propio producto, utilizando las opciones de ayuda («HELP») disponibles en cada programa. Básicamente, EasyReport está compuesto por los tres elementos siguientes:

1.2. Wedit

Nuevo editor que permite manejar ficheros de mayor tamaño que el incluido en versiones anteriores. Esta ampliación afecta tanto al número de caracteres por línea como al total de líneas. Estos límites se sitúan ahora aproximadamente en 20.000 caracteres por línea y 8.000 líneas de fichero.

Asimismo, este nuevo editor emplea diferentes colores para determinar palabras reservadas (negro), variables de usuario e internas (rojo), literales (azul), comentarios (verde), etc.

El comando encargado de la ejecución del editor es wedit, cuya sintaxis es la siguiente:

wedit [-v] | [-m] fichero [-l secuencia_a_buscar]
[-x extensión]

Donde:

-v: Cláusula opcional que indica la versión del comando, así como su «upgrade».

-m: Cláusula opcional que ejecuta el editor maximizado.

fichero: Parámetro que indica el nombre del fichero que se desea crear o editar.

-l secuencia_a_buscar: Cláusula opcional que permite acceder a un texto en un punto determinado por una secuencia de caracteres («secuencia_a_buscar») indicada por el usuario, de forma que el cursor aparezca posicionado en el primer carácter de la primera secuencia encontrada. Esta opción sólo tiene sentido para acceder a ficheros ya existentes, y es especialmente útil en documentos muy extensos.

-x extensión: Esta opción permite indicar la extensión que tendrán los ficheros generados.

Nota: Las cláusulas «-m», «-l» y «-x» pueden indicarse indistintamente antes o después del nombre del «fichero».

1.3. Comando ctlinf

Este comando que ya existía en la versión 2.0.05 para UNIX y MS-DOS, devuelve información sobre los programas y módulos que componen una aplicación realizada con MultiBase. Para más información consulte la página 12/11 del Manual del Administrador de MultiBase.

2. Nuevas funcionalidades y sugerencias implementadas

A continuación se indican las nuevas funcionalidades y mejoras implementadas en el producto respecto a la versión anterior en cada sistema operativo. Esta información se ha estructurado en los siguientes apartados:

Cuando alguna sugerencia o nueva funcionalidad es específica de un entorno concreto (UNIX, MS-DOS, Windows o red local), éste se indica entre corchetes antes del comentario correspondiente.

IMPORTANTE: El SQL y los «gateways» de la versión 3.0 son incompatibles con el CTL de versiones anteriores de MultiBase y viceversa. Por lo tanto, en instalaciones cliente-servidor ambas máquinas (cliente y servidor) tienen que disponer de la versión 3.0 del CTL y del CTSQL.

Todos los desarrollos realizados con versiones anteriores de MultiBase son compatibles con esta nueva versión.

2.1. Lenguaje CTL

[Red local en MS-DOS y Windows]. En entornos de red local sobre MS-DOS y Windows se ha evitado el bloqueo de las máquinas que se originaba al emplear un FORM y bloquear una fila mediante la instrucción MODIFY (operación de actualización) cuando desde un nodo de la red se recorría sobre dicha fila un CURSOR definido con la cláusula «FOR UPDATE». Y lo mismo sucedía cuando se empleaba un CURSOR con la cláusula «FOR UPDATE» desde ambos nodos.

[UNIX]. Cuando se definía un CURSOR «FOR UPDATE» sin emplear ningún índice para construir la tabla derivada (acceso secuencial), se originaba el siguiente bloqueo al acceder desde distintos puestos de trabajo: Si el primer puesto que ejecutaba el programa leía un número de filas físicamente anteriores en la tabla a las que debería leer el segundo puesto, éste se bloqueaba hasta que el primero cerraba el CURSOR.

Por ejemplo: Valores de la tabla a actualizar mediante un CURSOR «FOR UPDATE»:

Grupo Descripción
1 Valor1
1 Valor2
1 Valor3
2 Valor4
2 Valor5
2 Valor6

El primer puesto de trabajo leería las filas correspondientes al grupo «1»; si el segundo puesto leyese las correspondientes al grupo «2», éste quedaría bloqueado hasta que el primero cerrase el CURSOR después de leer la fila «1-Valor3».

En un mantenimiento (FORM) del tipo cabecera-líneas con ordenación de filas (cláusula «ORDER BY» en la sección JOINS), el programa se ralentizaba si existían muchas filas de detalle para una cabecera al tener que mostrar siempre la primera fila que cumpliese las condiciones de enlace. Este problema es debido al cambio del optimizador llevado a cabo en las versiones 2.0.xx de MultiBase. Para resolverlo basta con añadir en la cláusula «ORDER BY» de la sección JOINS las columnas de enlace entre ambas tablas.

Ejemplo:

f1 = cabecera.c1 = lineas.c1 required;
f2 = cabecera.c2 = lineas c2 required;

f3 = lineas.linea noentry noupdate;

joins
    lineas lines of cabecera order by c1, c2, linea
    composites <cabecera.c1, cabecera.c2> <lineas.c1, lineas.c2>
end joins

Si la tabla «lineas» tiene muchas filas para una «cabecera», indicar la sección JOINS según se indica en el ejemplo. De no hacerlo así, el programa funcionará igualmente, aunque de modo más lento.

Al leer un valor nulo («NULL») en un CURSOR, la variable de la cláusula «INTO» o «BY NAME» recogía blancos en lugar del valor nulo.

[Windows]. La instrucción WINDOW con la cláusula «AS FILE» no realizaba bien el «scroll» de la última página si ésta no se encontraba completamente llena, mostrándose parte de la información correspondiente a la página anterior.

La instrucción CANCEL dentro de la sección CONTROL de un FORM dejaba la columna componente de la clave primaria de la tabla a mantener con valor nulo («NULL»). Por ejemplo:

database almacen

define
form
tables
    provincias
end tables

control
    before delete of provincias
        select "1" from clientes
        where clientes.provincia = $provincias.provincia
        if found = true then cancel
end control
end form
end define

main begin
    menu form
end main

En el ejemplo anterior, si el operador eligiese la opción de borrado de la provincia en curso, y en ésta hubiese clientes, el programa cancelaba la operación de borrado, dejando la variable «provincias.provincia» a nulo. Si inmediatamente después se volvía a realizar la misma operación, se producía el borrado indebido de la provincia al no existir integridad referencial entre las tablas «clientes» y «provincias».

La instrucción WHENEVER con la cláusula «INTERRUPT» no se ejecutaba la segunda vez que se pulsaba la tecla de «break» del sistema operativo.

La condición «MATCHES» en una instrucción embebida en un módulo CTL no empleaba el índice definido para la columna, por lo que el acceso era bastante lento, mientras que sí lo hacía desde CTSQL. El problema era debido al análisis de la variable «host» empleada como condición.

[UNIX]. Al realizar una consulta sobre una columna de tipo «char» con los metacaracteres de la cláusula «MATCHES» en el mantenimiento de una tabla en un FORM, no se devolvía las mismas filas que si se ejecutaba a través del CTSQL la instrucción SELECT con las mismas condiciones.

[Windows]. Al ejecutar la instrucción «START OUTPUT STREAM» (con cláusula «APPEND») sobre un fichero existente que no tuviese permiso de lectura/escritura para el usuario que estuviese ejecutando el programa se producía el bloqueo de la máquina.

[Windows]. Al ejecutar la instrucción «START OUTPUT STREAM» sobre un fichero cuyo nombre estuviese incluido en una variable de tipo «char» de gran longitud (por ejemplo 500), si no se indicaba la cláusula «CLIPPED» se producía un error de protección general en Windows al intentar generar un fichero con un nombre compuesto por 500 caracteres. Actualmente, en este caso se produce un «CLIPPED» automático en este tipo de variables.

La variable interna «sqlrows» se activa con el número de filas leídas en una instrucción SELECT con la cláusula «INTO TEMP», tanto si se encuentra preparada como si no (instrucciones PREPARE y EXECUTE). Por el contrario, dicha variable no se activará cuando dicha instrucción SELECT se encuentre en una TSQL.

[Windows]. El primer icono de un menú «Lotus» desaparecía al ejecutar por segunda vez consecutiva un mantenimiento sobre una tabla en un FORM.

Las instrucciones BREAK y EXIT PROGRAM, dependiendo del lugar donde se incluyesen, no liberaban totalmente la memoria reservada.

En instalaciones cliente-servidor, la línea a insertar en el fichero «/etc/inetd.conf» de la máquina servidor, relativa al gestor de base de datos a emplear, debe indicar necesariamente la versión 3.0.

Por ejemplo:

a) En CTSQL:

ctsql stream tcp nowait root $TRANSDIR/lib/ctsql
ctsql system 3.0 0.0 NET

b) En Informix:

gwinformix stream tcp nowait root $TRANSDIR/lib/gwinformix
gwinformix system 3.0 $TRANSDIR/etc/gwinformix.env NET

c) En Oracle:

gworacle stream tcp nowait root $TRANSDIR/lib/gworacle
gworacle system 3.0 $TRANSDIR/etc/gworacle.env NET

Al ejecutar repetidamente la instrucción INPUT FRAME con la cláusula «FOR UPDATE», si el FRAME incluía el atributo LOOKUP en alguna de sus variables, el cruce no se borraba de la pantalla.

[Error de Documentación]. La cláusula «LABEL» de la instrucción PROMPT FOR puede ser también una expresión.

2.2. Gestor de base de datos (CTSQL)

Si se empleaba una función interna de CTSQL (en una cláusula «WHERE») relativa al tipo de dato «date» no se seleccionaba ninguna fila, siempre y cuando la columna «fecha» empleada como parámetro de la función fuera parte de un índice. Por ejemplo, el siguiente ejemplo no seleccionaba ninguna fila:

create table tabla (campo1 char(11) not null,
    fecha date not null,
    descripcion char(20) upshift)
primary key (articulo, fecha);

select * from tabla
    where tabla.articulo = "valor"
    and year(fecha) between 1990 and 1995

Las siguientes instrucciones SELECT no devolvían la tabla derivada correcta:

select * from provincias
    where provincia not between 1 and 4
    and provincia not between 5 and 7

select a,b from tabla
    where a not in ("S","N") or b not in ("S","N")

La creación de una base de datos con la cláusula «COLLATING» determinaba que ciertas condiciones (de la cláusula «WHERE») no devolviesen las filas correctas.

[HP-UX]. La lectura de una tabla en la que se condicionaba una columna de tipo «DECIMAL» o «MONEY» no devolvía la tabla derivada correcta.

La negación de una condición «IS NOT NULL» de CTSQL no seleccionaba las filas correctas. Por ejemplo:

select * from provincias
    where not (prefijo is not null)

Para una correcta optimización mediante el empleo del «ROWID», éste debe encontrarse a la izquierda de una condición. Por ejemplo:

select * from provincias
    where rowid = 20

Por el contrario, si se hubiese indicado:

select * from provincias
where 20 = rowid

No se optimizaría correctamente.

La integridad referencial entre dos tablas no se controlaba al actualizar (instrucción UPDATE) parte de la columna componente (substring) de la clave primaria de la tabla principal. Por ejemplo:

update provincias set col_primary[2,3] = "ab"
where ...

[Solaris]. Al ejecutar una instrucción SELECT que leía de una tabla temporal (cláusula «INTO TEMP») se producía un error de interrupción en la comunicación con el CTSQL.

[Solaris]. Al emplear la instrucción EDIT de una variable no se presentaba su contenido.

[UNIX]. La lectura del «ROWID» de una tabla con una condición «MATCHES» sólo devolvía la primera fila encontrada como válida. Sin embargo, si se leía alguna columna perteneciente a la tabla, sí devolvía la tabla derivada correcta. Este problema se detectaba entre la ejecución de la instrucción SELECT con la condición «MATCHES» y la consulta desde un FORM con la misma condición. Por ejemplo:

select * from articulos
where descripcion matches "M*e*"

En la base de datos de demostración incluida en su copia de MultiBase, esta instrucción SELECT devuelve varias filas. Si en lugar del asterisco seleccionábamos el «ROWID» sólo devolvía la primera fila que cumpliese la condición. Asimismo, si se ejecutaba el mantenimiento de «articulos» desde el FORM y se introducía la condición «M*e*» en el campo «descripcion» sólo se seleccionaba una fila.

Hacer un DELETE cuando existe un índice duplicado con muchas duplicidades resulta extremadamente lenta. Para agilizar esta operación hay que cambiar el índice duplicado por uno único compuesto por la columna o columnas duplicadas del índice inicial más la columna o columnas componentes de la clave primaria.

2.3. Enlace de programas (comando ctlink)

La creación de programas en UNIX y MS-DOS a partir de módulos fuente de CTL generados por MultiBase para Windows en los que se utilicen funciones específicas de este entorno, no provocará ningún error, asumiendo que dichas funciones también son internas de aquellos sistemas.

2.4. Depurador («debugger»)

A la hora de consultar el valor de una variable desde la línea de comando mediante «?variable», si aquella superaba los 80 caracteres no se mostraba su valor completo. Actualmente dicho valor se muestra en tantas líneas como sea necesario.

2.5. Entorno de desarrollo (Trans)

Al activar la opción «Ventana de BD» de la persiana «Entorno» se eliminan de la pantalla las ventanas de información relativas a la base de datos en curso y a las teclas de ayuda, información y selección.

Por su parte, en instalaciones cliente-servidor, al ejecutar el Entorno de Desarrollo se solicita el nombre del usuario («DBUSER») con el que se conecta a la máquina servidor, así como su clave de acceso («DBPASSWD»).

Por último, cuando un módulo se define con la opción «Depuración», todas las compilaciones se realizarán con «debugger» hasta que se especifique lo contrario.

2.6. Transacciones

La instrucción ROLLFORWARD producía el error «Fallo en rollforward» al intentar recuperar la ejecución provocada por la instrucción DELETE del SQL.

Todos los «cursores» definidos con la cláusula «FOR UPDATE» que se encuentren afectados por una transacción («BEGIN WORK») serán siempre «NOWAIT», teniendo que controlar el bloqueo de una fila mediante la variable interna «locked».

2.7. EasyReport (MS-DOS y UNIX)

Cuando se intentaba generar un listado que empleaba parámetros en su ejecución se producía un error no recuperable al intentar abrirlo.

2.8. Documentador

El documentador automático de MultiBase (Tdocu) producía un error no recuperable en las versiones para MS-DOS y Windows al generar el manual de usuario de un programa en el que se definía el atributo LOOKUP en una variable de un FRAME.

»