ifxtojava2

320
UNIVERSIDAD DE OVIEDO ESCUELA POLITCNICA SUPERIOR DE INGENIER˝A DE GIJN LENGUAJES Y SISTEMAS INFORM`TICOS PROYECTO FIN DE CARRERA N” 1082012 `NALISIS TEORICO/PR`CTICO DE LA TRADUCCIN DE UN LENGUAJE DE CUARTA GENERACIN A JAVA DOCUMENTO N” 1 MEMORIA `NGEL SU`REZ GARC˝A JULIO DE 2008 TUTOR: RAL IZQUIERDO CASTANEDO

Upload: joansago

Post on 22-Jan-2016

98 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: IfxToJava2

UNIVERSIDAD DE OVIEDO

ESCUELA POLITÉCNICA SUPERIOR DE INGENIERÍA DE GIJÓN

LENGUAJES Y SISTEMAS INFORMÁTICOS

PROYECTO FIN DE CARRERA Nº 1082012

ÁNALISIS TEORICO/PRÁCTICO DE LA TRADUCCIÓN DE UN LENGUAJE DE CUARTA GENERACIÓN A JAVA

DOCUMENTO Nº 1

MEMORIA

ÁNGEL SUÁREZ GARCÍA JULIO DE 2008

TUTOR: RAÚL IZQUIERDO CASTANEDO

Page 2: IfxToJava2

2

ÍNDICE: PREAMBULO ...........................................................................................................6 PLANTEAMIENTO 4GL...............................................................................................8 INTRODUCCION 4GL................................................................................................8 ESTUDIO DEL LENGUAJE INFORMIX-4GL .....................................................................9

INTERFACES DE UNA APLICACIÓN EN INFORMIX 9 PARTES DE UNA APLICACIÓN 10 CARACTERÍSTICAS BÁSICAS DEL LENGUAJE 12 TIPOS DE DATOS 17 EXPRESIONES 4GL 19

TRADUCTOR DEL LENGUAJE .................................................................................... 24 PRERREQUISITOS 24 ALCANCE Y LIMITACIONES 24 ANALIZADOR LEXICO 25 ANALISIS DE LA SINTAXIS 27 SEMANTICA, TABLA DE SIMBOLOS, Y MANEJO DE ERRORES 53 GENERACIÓN DE CÓDIGO 55

TRATAMIENTO DE SENTENCIAS DE INFORMIX-4GL ..................................................... 57 SENTENCIAS DE DEFINICIÓN DEL MÓDULO PRINCIPAL DE PROGRAMA 57 SENTENCIAS DE MANEJO DE FUNCIONES 70 SENTENCIAS DE CONTROL DEL FLUJO 74 SENTENCIA DE DEFINICIÓN DE MENÚS 79 SENTENCIAS DE DECLARACIÓN Y UTILIZACIÓN DE VARIABLES 83

ÁMBITO DE VARIABLES .......................................................................................... 86 PLANTEAMIENTO SQL............................................................................................. 89 ENFOQUE............................................................................................................. 89 PRERREQUISITOS.................................................................................................. 90 ESTANDARES SQL ................................................................................................. 91 CONVENCIONES DE SINTAXIS ................................................................................ 92 CLASIFICACIÓN DE LAS SENTENCIAS SQL................................................................. 93

SENTENCIAS SQL DE DEFINICIÓN DE DATOS 93 SENTENCIAS SQL DE MANIPULACIÓN DE DATOS 93 SENTENCIAS SQL DE MANIPULACIÓN DE CURSORES 93 SENTENCIAS SQL DE OPTIMIZACIÓN-INFORMACIÓN 93 SENTENCIAS SQL DE CONTROL DE ACCESO A LOS DATOS 93 SENTENCIAS SQL QUE GARANTIZAN LA INTEGRIDAD DE LOS DATOS 94 SENTENCIAS SQL DE MANIPULACIÓN DINÁMICA DE DATOS 94

ESTUDIO DE LAS SENTENCIAS SQL......................................................................... 94 SENTENCIA ALTER INDEX 94 SENTENCIA ALTER TABLE 95 SENTENCIA BEGIN WORK 102 SENTENCIA CLOSE 104 SENTENCIA CLOSE DATABASE 105 SENTENCIA COMMIT WORK 106 SENTENCIA CREATE AUDIT 106 SENTENCIA CREATE DATABASE 107 SENTENCIA CREATE INDEX 109 SENTENCIA CREATE SYNONYM 110 SENTENCIA CREATE TABLE 111 SENTENCIA CREATE VIEW 117

Page 3: IfxToJava2

3

SENTENCIA DATABASE 118 SENTENCIA DECLARE CURSOR 119 SENTENCIA DELETE FROM 120 SENTENCIA DROP AUDIT FOR 121 SENTENCIA DROP DATABASE 122 SENTENCIA DROP INDEX 122 SENTENCIA DROP SYNONYM 123 SENTENCIA DROP TABLE 124 SENTENCIA DROP VIEW 125 SENTENCIA EXECUTE 125 SENTENCIA FETCH 126 SETENCIA FLUSH 127 SENTENCIA FREE 128 SENTENCIA GRANT 128 SENTENCIA INSERT INTO 134 SENTENCIA LOAD FROM 135 SENTENCIA LOCK TABLE 136 SENTENCIA OPEN 138 SENTENCIA PREPAPRE 139 SENTENCIA PUT 140 SENTENCIA RENAME COLUMN 140 SENTENCIA RENAME TABLE 141 SENTENCIA REVOKE 141 SENTENCIA ROLLBACK WORK 143 SENTENCIA SELECT 143 SENTENCIA START 147 SENTENCIA UNLOAD 147 UNLOCK TABLE 148 SENTENCIA UPDATE 148 UPDATE STATISTICS 150

SENTENCIAS DE MANIPULACIÓN DINÁMICA DE DATOS Y CURSORES........................... 150 SENTENCIAS DE CONTROL DE FLUJO...................................................................... 153 ESTUDIO DE TIPOS DE DATOS .............................................................................. 154

TIPOS DATOS BASICOS 154 TIPOS DE DATOS JDBC 156 TIPOS DE DATOS INFORMIX-SQL 157 TIPO DE DATOS SQLSERVER 161 TIPOS DE DATOS DE ORACLE 164 TIPOS DE DATOS DE DB2 167 TABLA DE MAPEOS 169

MAPEO DE TIPOS DE DATOS ENTRE JDBC Y JAVA ..................................................... 172 FUNCIONES DE RECUPERACION DE DATOS SQL ....................................................... 174 CONVERSIONES DE TIPOS DE DATOS..................................................................... 175

TRATAMIENTO DE LAS CONVERSIONES NO IMPLICITAS 178 EXPRESIONES SQL .............................................................................................. 183

EXPRESIONES DE MANEJO DE COLUMNAS 184 EXPRESIONES DE CONSTANTES 188 FUNCIONES SQL 191 EXPRESIONES AGREGADAS 195 NOMBRES DE VARIABLES 196

Page 4: IfxToJava2

4

NOMBRES DE ELEMENTOS DE LA BASE DE DATOS .................................................... 196 OPERACIONES SOBRE EXPRESIONES SQL ............................................................... 197

TRATAMIENTO POR SQLSERVER 199 TRATAMIENTO PO ORACLE 203 TRATAMIENTO POR DB2 206 TRADUCCIÓN DE OPERADORES SOBRE EXPRESIONES 208

CONFIGURACIÓN LOCAL....................................................................................... 209 ELEMENTOS DE INFORMIX 210 ELEMENTOS DE SQLSERVER 211 ELEMENTOS DE ORACLE 212 ELEMENTOS DE DB2 213 ELEMENTOS DE JAVA 213 CONCLUSIONES Y EJEMPLO DE CONFIGURACIÓN 214

TRATAMIENTO DE LAS FECHAS.............................................................................. 216 RECONOCIMIENTO DE LAS FECHAS 217 MOSTRAR VALORES 217 INTERCAMBIO DE DATOS ENTRE JAVA Y EL GESTOR 218

CREACIÓN DE OBJETOS: PROPIETARIO Y ACCESO.................................................... 222 OBJETOS CREADOS EN INFORMIX 222 OBJETOS CREADOS EN SQLSERVER 222 OBJETOS CREADOS EN DB2 223 OBJETOS CREADOS EN ORACLE 223 CONCLUSIONES 224

CONFIGURACIÓN DE LA CONEXIÓN........................................................................ 225 PLANIFICACIÓN Y PRESUPUESTO........................................................................... 226 MANUAL DE USUARIO .......................................................................................... 229

REQUISITOS HARDWARE 229 REQUISITOS SOFTWARE 229 CONFIGURACIÓN 230 EJECUCIÓN DEL TRADUCTOR 233 VERIFICACIÓN DE FUNCIONAMIENTO 234

ANEXO I: FUENTES.............................................................................................. 235 EJEMPLO SENTENCIA ALTER TABLE 235 EJEMPLO SENTENCIAS CONEXIÓN/DESCONEXIÓN 237 EJEMPLO SENTENCIAS DE TRATAMIENTO DE TRANSACCIONES 237 EJEMPLO SENTENCIA CREACION INDICE 238 EJEMPLO SENTENCIA CREACION DE SINONIMOS 239 EJEMPLO SENTENCIA CREACION DE TABLA 242 EJEMPLO SENTENCIAS CREACION TABLA TEMPORAL 243 EJEMPLO SENTENCIA CREACION VISTA 245 EJEMPLO SENTENCIA DELETE 247 EJEMPLO SENTENCIA DROP INDEX 248 EJEMPLO SENTENCIA DROP OBJETO 249 EJEMPLO SENTENCIA GRANT 251 EJEMPLO SENTENCIA INSERT 251 EJEMPLO SENTENCIA LOAD/UNLOAD 252 EJEMPLO SENTENCIA LOCK/UNLOCK 253 EJEMPLO SENTENCIA RENAME COLUMN 254 EJEMPLO SENTENCIA RENAME TABLA 255 EJEMPLO SENTENCIA PREPARE/EXECUTE � PREPARE/DECLARE 256

Page 5: IfxToJava2

5

EJEMPLO SENTENCIA DECLAREFORUPDATE 258 EJEMPLO SENTENCIA FOREACH-FORUPDATE 262 EJEMPLO SENTENCIA TIPOS DE DATOS 267 EJEMPLO DE MANEJO DE COLUMNAS Y CONSTANTES PREDEFINIDAS 269 EJEMPLO DE MANEJO DE LITERALES, CONSTANTES Y VARIABLES 272 EJEMPLO FUNCIONES DE MANEJO DE FECHAS 275 EJEMPLO DE FUNCIONES MATEMÁTICAS 280 EJEMPLO DE FUNCIONES AGREGADAS 283 EJEMPLO DE FUNCION WEEKDAY 284 EJEMPLO DE MANEJO DE OPERACIONES SOBRE EXPRESIONES 288 EJEMPLO DE MANEJO DE CONSTANTES TIPO FECHA 305

ÍNDICE DE FIGURAS ............................................................................................ 315 ÍNDICE DE TABLAS.............................................................................................. 316 INDICE DE CUADROS........................................................................................... 318 REFERENCIAS BIBLIOGRAFICAS............................................................................. 319

Page 6: IfxToJava2

6

PREAMBULO La idea de este proyecto surgio hace varios años, sobre el año 2001, cuando trabajaba en una empresa cuyo principal producto era un ERP el cual estaba desarrollado en Informix-4GL y funcionaba sobre el gestor de bases de datos Informix-SE (Standard Engine). Debido al futuro incierto de Informix Software Inc. y por añadidura de sus productos y a la necesidad de innovación técnologica del producto los directivos de la empresa se plantean evolucionar el mismo.

Esta evolución viene marcada por dos premisas fundamentales:

Reutilización de código. Se Habían desarrollosado miles de ficheros de código fuente que se pretendia reutilizar en la medida de lo posible.

Aportar un interfaz gráfico como front-end de la aplicación. Informix permitia el desarrollo de aplicaciones en modo carácter y se puso como objetivo el aportar un interfaz más amigable basado en un entorno gráfico.

Aunque mi carrera profesional se desvinculo de dicha empresa, en el años 2002, el proyecto en que se había embarcado ésta me parecio muy interesante tanto nivel personal como, incluso, comercial. Antes de mi marcha ya se podian ver los primeros resultados de dicho proyecto y sobre todo en el aspecto visual no alcanzaba los objetivos esperados, básicamente habría una ventana de MS-DOS y cargaba la aplicación aportando unicamente relieve, colorido y posibilidad de utilizar ratón, pero manteniendo el aspecto de la aplicación original y no utilizando las posibilidades gráficas que ofrecen las API�s de Windows. Ante esta situación decido seguir por mi cuenta con el traductor de código fuente Informix-4GL marcandome unos objetivos más ambiciosos:

Reutilización de miles/millones de líneas de código fuente. (sin necesidad de modificar para ello el código fuente).

Aportar aspecto visual y un interface más amigable para el usuario, utilizando para ello los recursos que posiblitan los sistemas actuales.

Generar un código objeto legible, entendible y fácilmente modificable/ampliable.

Generar código objeto multimódulo y multiplataforma.

Permitir trabajar con diferentes gestores de bases de datos (otros aparte de Informix-SE).

El estudio, teorico-práctico, que se realiza en este proyecto trata de cuplir estos objetivos y para ello se divide en dos partes diferenciadas:

Sección 1: Estudio del lenguaje de programación Informix-4GL. En esta primera parte se estudia el lenguaje Informix-4GL, se desarrolla un traductor de Informix-4GL a JAVA donde el análisis sintáctico se encarga de reconocer la sintaxis completa de Informix y se genera código objeto JAVA para el mismo.

Sección 2: Estudio del SQL de Informix. En esta segunda parte se estudia la Sintaxis de las sentencias SQL de Informix, se evalúa la compatibilidad y posibilidad de ejecución sobre los gestores de bases de datos estudiados. Este estudio se focaliza en los gestores de bases de datos: Informix, Oracle, SqlServer y DB2.

En función del análisis realizado y del gestor de bases de datos para el que se este generando código se transformaran, si es preciso y posible, las sentencias SQL que aparecen en el código fuente de tal forma que tengan el mismo comportamiento sobre el gestor de bases de datos destino que sobre el original.

Page 7: IfxToJava2

7

ESTUDIO DEL LENGUAJE DE PROGRAMACIÓN INFORMIX-4GL

Page 8: IfxToJava2

8

PLANTEAMIENTO 4GL Dentro de esta sección se estudiará el lenguaje de programación Informix-4GL, su sintaxis y semántica y en base a ello se construirán todos los componentes del traductor de tal forma que el programa generado permita la traducción de ficheros fuentes .4GL a ficheros objeto .JAVA funcionalmente correctos.

Como paso previo del análisis se hará una breve introducción al lenguaje de programación Informix-4GL con objeto de hacerse una idea global del mismo sus características y componentes así como de denotar la complejidad y amplitud del mismo.

Posteriormente ya se entra en profundidad a describir cada uno de los elementos del traductor haciendo hincapié en aquellas temas que merecen especial atención, destacando principalmente las características del componente de generación de código.

Una vez explicados los componentes del traductor se pasa a analizar con total detalle la sentencias 4GL estudiadas destacando entre ellas: el tratamiento de los programas multimódulo, el módulo �GLOBALS� y la sentencia MENU.

Como elemento a destacar dentro del tratamiento de las sentencias 4GL es la posibilidad que se ofrece de aportar un entorno gráfico a los programas generados lo cual es una de las mayores aportaciones con respecto a los programas originales.

INTRODUCCION 4GL La Compañía Informix Software Inc. desarrollo un entorno de programación con su propio lenguaje de 4ª generación: Informix-4GL el cual esta diseñado especialmente para aplicaciones que trabajan con bases de datos y en particular para el gestor de base de datos Informix-SE.

Informix-4GL es un lenguaje de 4ª generación que, aparte de las características típicas de cualquier otro lenguaje: declaración de variables y funciones, sentencias de control de flujo del programa, etc., soporta características especiales para llevar a cabo las siguientes acciones:

Consultas y manejos de bases de datos usando SQL. Informix-4GL incluye todas las sentencias SQL, soportadas por Informix, como sentencias nativas del propio lenguaje.

Informix-4GL admite embebidas sentencias SQL que son una extensión del Standard Query Language (SQL) desarrollado por IBM y cumple el nivel I del Standard de lenguajes de bases de datos (X3.135-1986).

Preparar informes de datos de la base de datos o de otra fuente. Un informe, report, es un bloque de programa especializado que permite mostrar datos de la base de datos. La salida de un informe es normalmente tabular y puede ser diseñada para imprimir con cabeceras y pies de página, siendo los dispositivos de salida posibles: pantalla, fichero, e impresora.

Generación de formatos de pantalla o formularios, y menús en aplicaciones multiusuario. Los formatos de pantalla se diseñan de forma independiente al programa.

Page 9: IfxToJava2

9

ESTUDIO DEL LENGUAJE INFORMIX-4GL En este punto se pretende mostrar las características y componentes del lenguaje Informix-4GL con objeto de hacer ver la amplitud del mismo y de la gran cantidad de elementos a tener en cuenta a la hora de hacer la traducción del mismo a otro lenguaje.

INTERFACES DE UNA APLICACIÓN EN INFORMIX

Figura 1: Interfaces proporcionados por Informix-4GL

Una aplicación multiusuario escrita en Informix-4GL, como se muestra en la figura anterior tiene cuatro interfaces primarios:

Acceso a bases de datos a través del servidor de bases de datos Informix. Los programas escritos en Informix-4GL pueden acceder a bases de datos relacionales con un servidor de bases de datos de Informix apropiado.

La base de datos puede estar situada en el mismo equipo que la aplicación 4GL aunque a menudo la aplicación se ejecuta desde un sistema cliente separado.

Una vez que la conexión de red es correctamente establecida, el acceso a la base de datos es transparente para el usuario. Un mismo programa 4GL puede trabajar con un servidor de bases de datos local o con servidor de bases de datos de red.

Comunicación con el usuario a través de una Terminal. La iteración del programa con los usuarios es a través de áreas de pantalla, llamadas ventanas, las cuales tienen un tamaño fijo de caracteres por fila y columna. El usuario de una aplicación puede usar los siguientes entornos:

Un emulador de Terminal en su ordenador personal o estación de trabajo que se conecta al sistema UNIX.

Un Terminal carácter conectado al sistema UNIX.

El Interface de usuario de Informix-4GL es programado en modo carácter. Una ventana 4GL puede mostrar un número fijo de caracteres horizontal y verticalmente. Cuando se declara una ventana en Informix-4GL se deben de especificar las dos dimensiones. Cada ventana 4GL no puede mostrar más de un formulario al mismo tiempo.

Acceso a ficheros secuenciales del sistema operativo. Las aplicaciones pueden usar ficheros de datos secuenciales, o planos, en las siguientes formas:

Ficheros de datos

Informes

Base de datos

Ventanas 4gl

Usuarios de la base de datos

Page 10: IfxToJava2

10

Con la sentencia UNLOAD que escribe las filas seleccionadas de una tabla de la base de datos en un fichero especificado.

Con la sentencia LOAD que lee un fichero y inserta sus líneas como filas en una tabla especifica de la base de datos.

Las sentencias START REPORT o REPORT que pueden enviar la salida del formulario a un fichero secuencial o a un comando del sistema operativo.

La sentencia PRINT FILE que puede incorporar el contenido de un fichero en la salida de un formulario de Informix-4GL.

La sentencia DISPLAY que puede ser usada para escribir en pantalla. Usando comandos del sistema operativo se puede redireccionar la salida a un fichero o a otro programa.

Generación de informes que pueden ser enviados a diferentes destinos. Los programas escritos en Informix-4GL pueden generar potentes y flexibles informes, cuya salida es una serie de líneas impresas. La salida puede se redireccionada a uno de las siguientes destinos:

La pantalla.

Una impresora.

A un fichero secuencial.

A una tubería del sistema operativo hacia otro proceso.

La lógica para generar informes es la misma en todos los casos. El destino puede ser preestablecido al codificar el programa o determinado en tiempo de ejecución.

PARTES DE UNA APLICACIÓN

Toda aplicación realizada en Informix-4GL, como se muestra en la siguiente figura, puede estar compuesta de los siguientes tipos de ficheros:

Código fuente de pantallas (.PER). En ellas se especifica el interfaz de usuario de la aplicación usando para ello ficheros editables (formato texto) en los que se especifica la apariencia visual del formulario y los tipos de datos y atributos de los campos del formulario.

Los ficheros de especificación de formularios son ficheros ASCII. Se puede usar un editor de texto para diseñar las etiquetas y los campos del formulario.

Una vez diseñado el formulario, este se compila con lo que se obtiene el fichero objeto del formulario (.FRM), el cual es un fichero binario portable a cualquier plataforma que soporte 4GL. Este fichero objeto es el que carga Informix-4GL durante la ejecución.

Ficheros fuente de mensajes (.MSG). El usuario puede escribir textos de ayuda u otros mensajes de forma independiente al los programas 4GL. Así los programas pueden compartir un conjunto de mensajes y se pueden cambiar estos de forma independiente al programa.

Este tipo de ficheros de mensajes son muy utilices para hacer los programas multilenguaje sin tener que para ellos definir programas diferentes.

Los ficheros de mensajes son compilados obteniendo así un fichero de mensajes objeto (.IEM) el cual esta indexado para obtener así un acceso rápido. Igual que los formularios un fichero objeto de mensajes puede ser usado en diferentes aplicaciones.

Page 11: IfxToJava2

11

Figura 2: Ficheros de los que consta una aplicación en Informix

Fichero fuente de programa (.4GL). Se pueden escribir un programa en uno o más ficheros fuentes de código fuente 4GL. En estos ficheros se especifica la lógica de programa a través de sentencias 4GL en los ficheros fuentes del mismo.

Debido a que Informix-4GL es un lenguaje de programación estructurado, las sentencias ejecutables deben aparecer solo dentro de secciones lógicas del código fuente llamadas: bloques de programa. Estas pueden ser la sentencia MAIN, REPORT, o FUNCTION. En un programa pequeño se pueden escribir todas las funciones dentro de un mismo fichero, pero cuando el programa crece, y por razones de organización, suele ser habitual definir funciones en ficheros separados.

Cada fichero fuente, normalmente, refleja una unidad lógica de programa.

La ejecución de todo programa comienza de forma obligatoria con el bloque de programa llamado MAIN. El módulo de código fuente que contiene la sentencia MAIN es llamado: el módulo MAIN. A continuación se muestra un pequeño, pero completo, programa 4GL:

MAIN CALL ejemplo() END MAIN FUNCTION ejemplo() DISPLAY "Hola, mundo" END FUNCTION

En la implementación RDS los ficheros fuentes de 4GL son compilados y generan un pseudo código (.4go) el cual es independiente de la maquina y no es directamente ejecutable por el sistema operativo. Este debe ser interpretado por el intérprete de Informix-4GL.

Cuando una aplicación tiene varios módulos fuente, primero se compilan estos generando módulos objeto separados y posteriormente se deben de concatenar estos para generar el fichero (.4gi) que pueda ser interpretado por Informix. La forma de hacer esto es mediante la creación de un fichero makefile. A continuación se muestra un ejemplo de makefile:

.SUFFIXES: .4go .4gl

C od io fu en te 4 g l

.4 g l

Fich eros de m en sa jes E specificacionde form a tos

F or m atoscom pilados

F ich eros de m esa jescom pilados

C od igo fu en te com pilado

Page 12: IfxToJava2

12

.4gl.4go: @(echo 'Compilando $*' ; cd `dirname $<` ; fglpc $< )

PACTINV= mbuscom.4go\ mbuscoma.4go\ mcar.4go\ mcript.4go\ mtrapal.4go pactinv.4gi: $(PACTINV) makefile @echo 'Linkando pactinv.4gi' ; cat $(PACTINV) > pactinv.4gi

CARACTERÍSTICAS BÁSICAS DEL LENGUAJE

Informix-4GL soporta la programación estructurada. Este diseño estimula la construcción de los programas como una familia de funciones simples y reutilizables. Además tiene sintaxis abierta y permite distintos estilos de programación. Los programas escritos en Informix-4GL son fácilmente refinables e incrementables.

En los puntos siguientes se especifican todas las características de este lenguaje de tal forma que se pueda adquirir una idea concisa del mismo:

Sensible al contexto. Informix-4GL no hace distinción entre mayúsculas y minúsculas en las palabras reservadas o identificadores del código fuente. Aunque si lo hace en las cadenas de caracteres introducidas entre comillas. Admite tanto la comilla simple (�) como la comilla doble (�) como delimitador de literales.

Se pueden intercalar letras mayúsculas y minúsculas en los nombre de identificadores, aunque durante el proceso de compilación los identificadores son pasados a minúsculas.

Espacios, delimitadores de marca, símbolos de escape y delimitadores. Al igual que en C y Pascal, el lenguaje Informix-4GL es de formato libre. Los espacios en blanco, tabulaciones, y saltos de línea son ignorados en la mayoría de los contextos, así como los comentarios.

Se debe de introducir, al menos, un espacio en blanco entre dos palabras reservadas, identificadores, o literales consecutivos en la misma línea, a no ser que otro separador se haya introducido. No se pueden meter espacios en blanco dentro de una palabra reservada o identificador. Los espacios en blanco en los literales son considerados, por Informix-4GL, como parte de éste.

El usuario puede usar libremente estos espacios en blanco para hacer más fácil de leer el código fuente 4GL.

No se pueden mezclar doble comilla y simple como delimitador de una misma cadena, por ejemplo la siguiente no es una cadena valida:

�No es una cadena valida�

Para incluir el delimitador de literales dentro de una cadena de caracteres se debe de preceder dicho literal con la barra invertida (\) o bien incluir dicho delimitador de cadena dentro de el otro delimitador de cadena. Ejemplos:

�Escriba \�Y\� para continuar�

�Escriba �Y� para continuar�

�Escriba �Y� para continuar�

El compilador de Informix-4GL considera la barra invertida (\) como el carácter de escape por defecto y considera el carácter que le siga inmediatamente como un literal sin darle ningún significado especial. Para especificar que algo incluye como parte de si la barra invertida se debe de introducir la doble barra invertida (\\) en el lugar donde la simple barra se quiere que aparezca. Igualmente se usa \\\\ para representar la doble barra invertida.

Page 13: IfxToJava2

13

Salvo en alguna sentencia preparada (PREPARE), en la sentencia PRINT y en la palabra reservada END SQL dentro de bloques SQL , Informix-4GL no requiere delimitador de sentencias aunque opcionalmente se puede utilizar el punto y coma (;) como delimitador.

Conjunto de caracteres Validos. Informix-4GL requiere el conjunto de caracteres ASCII, aunque también soporta caracteres propios del cliente en fechas, identificadores, especificación de pantallas y reportes.

Sentencias 4GL. Un módulo fuente de Informix-4GL puede contener sentencias y comentarios:

La sentencia es la unidad lógica de código en programas 4GL.

Un comentario es una especificación que Informix-4GL descarta.

No se pueden dividir una sentencia simple de Informix-4GL en varios módulos. Esta regla es también aplicable para sentencias compuestas. Informix-4GL tiene características que permiten ensamblar grandes programas a partir de múltiples módulos de código fuente de forma sencilla.

Las sentencias de Informix-4GL pueden contener: identificadores, palabras reservadas, literales, constantes, operadores, paréntesis y expresiones.

Informix distingue entre: sentencias SQL (Structured Query Language) y sentencias 4GL.

Comentarios. Un comentario es un texto incluido dentro del los módulos 4GL para ayudar a los lectores del código fuente, pero dicho texto es ignorado por el compilador de Informix-4GL.

Los comentarios se especifican de distintas formas:

Un comentario puede empezar por una llave abierta ({) y finalizar con una llave cerrada (}). Este puede tener una o más líneas.

El símbolo de almohadilla (#) indica el principio de un comentario que termina al final de la misma línea.

También se puede usar un par de signos menos (--) para indicar el principio de un comentario que termina al final de la línea. Este comentario es el especificado por el Standard ANSI para SQL.

Informix-4GL ignora todo el texto incluido entre llaves o desde # o -- hasta el final de la línea.

Cuando se usan comentario se deben de tener en cuenta las siguientes restricciones:

Dentro del una cadena de caracteres delimitada con comillas, Informix-4GL interpreta el símbolo de comentario como un literal mas y no como un indicador de comentario.

Los comentarios son admitidos dentro de la sección SCREEN de los ficheros de especificación de pantallas.

El símbolo # no se entiende como inicio de un comentario en un fichero de especificación de pantallas, en una sentencia SQL o en el texto de una sentencia preparada.

No se pueden usar las llaves como comentario dentro de un comentario.

No se pueden especificar dos signos menos seguidos como parte de una expresión aritmética ya que Informix-4GL interpreta que lo que sigue es un comentario. Se debe introducir un espacio en el medio o bien patentizarlos para separar los signos menos consecutivos.

módulos de código fuente y bloques de programa.

Para se crean programas 4GL se deben de introducir sentencias y comentarios dentro de uno o más ficheros de código fuente llamados módulos, cuyo nombre no puede exceder de 10 caracteres excluyendo la extensión del fichero.

Page 14: IfxToJava2

14

Debido a que Informix-4GL es un lenguaje estructurado, las sentencias ejecutables son organizadas dentro de grandes unidades llamadas bloques de programa. Los módulos 4GL pueden incluir tres tipos diferentes de bloques: MAIN, FUNCTION, y REPORTS.

Figura 3: Tipos de bloques en un programa

Cada bloque comienza con la palabra reservada con la cual luego será reconocido, y termina con la palabra reservada END correspondiente con cada tipo de bloque (EN MAIN, END FUNCTION, o END REPORT).

A continuación se detallan las reglas aplicables en la construcción de los bloques de programa:

Todo programa 4GL debe contener exactamente un bloque MAIN. Este debe de ser el primer bloque de programa en el módulo en el cual aparezca.

A excepción de ciertas declaraciones: DATABASE, DEFINE y GLOBALS no pueden aparecer sentencias 4GL fuera de un bloque de programa.

Las variables que se declaran dentro de bloques de programa su ámbito es el propio bloque en el cual se declaran. Étas no pueden ser utilizadas desde otro bloque de programa. Las variables que se declaran fuera de un bloque de programa tienen un ámbito hasta el final del módulo en el cual son declaradas.

Los bloques de programa no pueden partirse. Nunca pude ningún bloque de programa ser dividido en más de un módulo de programa.

La sentencia DATABASE tiene efectos en tiempo de compilación cuando aparece antes del primer bloque de programa del módulo. Dentro de bloques de programa tiene efectos en tiempo de ejecución.

El ámbito de la sentencia WHENEVER se extiende desde la primera vez que aparece hasta su próxima ocurrencia o bien hasta el fin del módulo en el cual es declarada, pero la sentencia WHENEVER no puede aparecer fuera de un bloque de programa.

Las sentencias: CALL, RETURN, EXIT PROGRAM, START REPORT, OUTPUT TO REPORT, FINISH REPORT, y TERMINATE REPORT y cualquier otra expresión 4GL que incluya una función predefinida como un operador pueden transferir el control de ejecución del programa entre distintos bloques del programa.

Bloques de Sentencias. Informix-4GL define sentencias simples y sentencias compuestas: aquellas que pueden contener otras sentencias. Las sentencias: MAIN, FUNCTION, Y REPORT son casos especiales de sentencias compuestas.

Las sentencias compuestas se muestran en la siguiente tabla:

CASE FOREACH INPUT PROMPT

CONSTRUCT FUNCION INPUT ARRAY REPORT

DISPLAY ARRAY GLOBLAS MAIN SQL

FOR IF MENU WHILE

Tabla 1: Sentencias compuestas de Informix-4GL

Page 15: IfxToJava2

15

Todo sentencia compuesta soporta la palabra reservada END para indicar en fin de la misma. La mayoría de las sentencias compuestas también soportan la palabra reservada: EXIT para transferir el control de ejecución a la sentencia que sigue a continuación de la finalización de la sentencia compuesta actual.

Por definición toda sentencia compuesta puede contener al menos una sentencia de bloque, un grupo de una o más sentencias SQL consecutivas o otras sentencias 4GL.

Informix-4GL permite que las sentencias de bloque sean vacías. Esta característica permite compilar y ejecutar aplicaciones que no contengan funciones o reports para probar el comportamiento de programas aún no completos.

A diferencia de los bloques de programas, los cuales no pueden ser anidados, los bloques de sentencias 4GL pueden contener otros bloques de sentencias.

La sentencia: GLOBALS puede incorporar indirectamente bloques de sentencias a través del fichero referenciado. Las sentencias del fichero especificado son incorporadas en el módulo actual durante la compilación.

Identificadores 4GL. Sentencias y especificaciones de formatos de pantalla pueden hacer referencia a algunas entidades de los programas 4GL por su nombre. Para crear nombres para las entidades de programa se declaran los identificadores.

Un identificador es una cadena de caracteres que es declarada como el nombre de una entidad de programa que ha de seguir las siguientes reglas:

Debe incluir al menos un carácter y no más de 50.

Solo letras ASCII, dígitos y el carácter de subrayado (_) son admitidos. Blancos, guiones y otros caracteres no alfanuméricos no son admitidos.

El carácter inicial debe de ser una letra o un subrayado.

Los identificadores 4GL no son sensibles al contexto.

Se pueden obtener resultados inesperados si se declara como un identificador ciertas palabras reservadas de SQL, de los lenguajes C y C++ o del sistema operativo o red.

Reglas para nombrar los Identificadores SQL. Las reglas para los identificadores SQL son similares a las de los identificadores 4GL, con las siguientes excepciones:

La longitud de los identificadores SQL esta limitada a no más de 18 caracteres.

Los identificadores SQL entre comillas si son sensibles al contexto.

Se pueden usar palabras reservadas como identificadores SQL, aunque se requieren cualificadores y puede hacer el código difícil de mantener.

Identificadores 4GL pueden ser iguales que identificadores SQL, pero esto requiere una especial atención dentro del ámbito de los identificadores 4GL.

Ámbito de referencia de los identificadores 4GL. Los identificadores 4GL se caracterizan por su ámbito de referencia. Un punto del programa donde una entidad puede ser referenciada por su identificador se dice que esta dentro del ámbito de referencia del identificador, por el contrario un punto del programa donde el identificador no es reconocido se dice que esta fuera del ámbito de su referencia.

El ámbito de referencia de una variable se determina en función de donde aparece la sentencia DEFINE, que declara el identificador, en el módulo fuente 4GL. Los identificadores de variables pueden ser: locales, de módulo o, en algunos casos globales a todo el programa. A continuación se indica el ámbito de los mismos:

La variables 4GL locales son declaradas dentro de un bloque de programa. Estas variables no pueden ser referenciadas por sentencias fuera del mismo bloque de programa.

Las variables de módulo, también llamadas modulares o estáticas, pueden ser declaradas fuera de cualquiera bloque de programa: MAIN, REPORT, o FUNCTION. Estos

Page 16: IfxToJava2

16

identificadores no pueden ser referenciados fuera del módulo 4GL en el que se han declarado.

Si dentro de la sentencias GLOBALS � END GLOBALS se declaran variables en un módulo, se puede extender el ámbito de dichas variables a otro módulo que incluya la sentencia GLOBALS <nombre de fichero> donde <nombre de fichero> especifica el fichero que contiene la declaración de la sentencia GLOBALS� END GLOBALS.

Hay nombres de constantes: NOTFOUND, TRUE y FALSE, y variables incorporadas como: status, int_flag, quit_flag y el registro SQLCA cuyo ámbito es global. Estos identificadores predefinidos no es necesario sean declarados, son visibles en todas las sentencias 4GL y pueden ser referenciados desde cualquier módulo 4GL. Ocurre lo mismo con las funciones incorporadas y los operadores tales como LENGTH() y INFIELD().

También son de ámbito global los nombres de ventanas, formatos de pantalla, reports y funciones. El ámbito de los identificadores de los formatos de pantalla incluye todas las sentencias 4GL que son ejecutadas mientras el formato de pantalla esta abierto.

La siguiente tabla resume el ámbito de referencia de los identificadores 4GL para varios tipos de entidades de los programas 4GL:

Entidad de Programa Ámbito de referencia

Constantes Global

Argumentos Local a su función o report.

Variable Módulo (si es declarada fuera de todo bloque de programa)

Local ( si es declarada dentro de un bloque de programa)

Campos de screen, arrays o records Mientras el formato de pantalla permanezca abierto

Identificadores de Pantalla o ventanas Globales (a partir de que son declarados)

Sentencias label Local al bloque de programa en el cual aparece

Tabla 2. Ámbito de referencia de los identificadores 4GL

Dentro de cada ámbito, cada identificador 4GL debe de ser único. Tampoco puede tener el mismo nombre un argumento de función o report que el propio identificador de dicha función o report.

Ámbito y visibilidad de los identificadores SQL. Por defecto el ámbito de un cursor o un objeto preparado es desde su declaración hasta el final del módulo o hasta que específicamente es liberado. El resto de los identificadores SQL tienen ámbito global.

Una vez liberado una sentencia preparada (PREPARE) o declarada (DECLARE) no puede volver a utilizarse el mismo nombre para referenciar otra.

Las sentencias no pueden hacer referencia a elementos de la base de datos tal como: tablas, columnas, o índices hasta que la base de datos que contiene dicho elemento no sea abierta.

Si se asigna a un elemento 4GL el nombre de otro SQL, el primero tiene precedencia dentro de su ámbito. Para evitar ambigüedades en las sentencias DELETE, INSERT, SELECT, Y UPDATE (y en solo estas), se puede utilizar el prefijo (@) al nombre de una tabla o columna que tenga el mismo nombre que una variable 4GL. En cualquier otro caso el identificador 4GL es visible en cualquier contexto ambiguo.

Variables con igual identificador. En tiempo de compilación se produce un error si se declara el mismo nombre a dos variables que tengan el mismo ámbito. Aunque si se puede declarar el mismo nombre si ambas variables tienen distinto ámbito.

Page 17: IfxToJava2

17

Si una variable local tiene el mismo nombre que una variable global o de tipo módulo, la variable local tiene precedencia dentro del bloque de programa en el cual es declarada. En cualquier otra parte del programa el identificador hará referencia a la variable global o de tipo módulo.

Una variable de tipo módulo puede tener el mismo nombre que una variable global si esta es declarada en un módulo diferente. Dentro del módulo en el cual es declarada, la variable tipo módulo tiene precedencia sobre la variable global. Las sentencias de dicho módulo no podrán hacer referencia a la variable global.

En resumen: en la porción de programa donde más de una variable tiene el mismo identificador, Informix-4GL da precedencia a las variables tipo módulo sobre las globales, y a las variables locales sobre las de cualquier otro ámbito.

TIPOS DE DATOS

En Informix-4GL toda variable ha de ser declarada de un tipo de dato. Un tipo de dato permite definir el tipo de información que puede ser almacenada y el tipo de operaciones que se puede hacer con él.

El usuario debe declarar el tipo de dato para cada variable, argumento de funciones y reports y los valores de retorno de las funciones. Los argumentos de funciones y reports puedes ser de cualquier tipo 4GL a excepción de ARRAY.

En ocasiones el valor almacenado como un tipo de dato puede ser convertido a otro.

La siguiente tabla muestra los tipos de datos soportados por Informix-4GL:

Tipo de Dato 4GL Tipo de valor que almacena

ARRAY OF type Arrays de valores de cualquier otro tipo de dato 4GL simple

BYTE Un tipo de dato binario cuya longitud es 231 bytes

CHAR(tamaño) Cadena de caracteres de cómo máximo 32767 bytes de longitud

CHARACTER Esta palabra reservada es sinónimo de CHAR

DATE Especifica una fecha

DATETIME Especifica una fecha y la hora del día

DECIMAL(p, s) Número en formato punto fijo, con una parte entera de longitud (p) y una parte decimal de longitud (s)

DECIMAL(p) Número en formato punto fijo, con una parte entera de longitud (p)

DEC Esta palabra reservada es sinónimo de DECIMAL

FLOAT Número en formato punto fijo de cómo máximo 32 dígitos de longitud

DOUBLE PRECISION Esta palabra reservada es sinónimo de FLOAT

INTEGER Número entero cuyo valor puede oscilar entre el rango: -2.147.483.647 a + 2.147.483.647

INT Esta palabra reservada es sinónimo de INTEGER

INTERVAL Extensión de tiempo en años y meses o una unidad de tiempo mas pequeña

Page 18: IfxToJava2

18

MONEY Cantidad de moneda con una escala y precisión

NUMERIC Esta palabra reservada es sinónimo de DECIMAL

REAL Esta palabra reservada es sinónimo de SMALLFLOAT

RECORD Conjunto de valores, de distintos tipos de datos, ordenados

SMALLFLOAT Número en formato punto fijo, de cómo máximo 16 dígitos de precisión

SMALLINT Número entero con un rango de �32767 a 32767

TEXT Cadena de caracteres de longitud máxima 232 bytes

VARCHAR(tamaño) Cadena de caracteres de longitud variable, su tamaño a de ser menor de 255 bytes

Tabla 3: Tipos de datos 4GL

Con la excepción de ARRAY y RECORD, los tipos de datos 4GL corresponden con los tipos de datos SQL validos en los servidores de bases de datos Informix. Los tipos de datos 4GL son un superconjunto de los tipos de datos SQL, que los servidores de bases de datos Informix admiten, con las siguientes excepciones:

El tipo de dato SERIAL de SQL no es un tipo de dato 4GL. Se debe usar el tipo de dato INTEGER para guardar los tipos de datos SERIAL recibidos de la base de datos. No se puede usar la palabra reservada SERIAL en una sentencia 4GL que no sea una sentencia SQL.

4GL no reconoce los tipos de datos NCHAR Y NVARCHAR. Cuando el servidor de bases de datos retorna un tipo de dato NCHAR este es convertido de forma automática a un valor CHAR, y no se puede �updatar� un tipo de dato NCHAR con un tipo de CHAR. De forma similar NVARCHAR es convertido en VARCHAR y un tipo de dato VARCHAR no puede �updatar� un campo de la base de datos de tipo NVARCHAR.

4GL no reconoce los tipos de datos: ITFIXED, BITVARYING, BLOB, BOLEAN, CLOB, DISTINCT, INT8, LIST, LVARCAHR, MULTISET, OPAQUE, REFERENCE, ROW, SERIAL8, SET, o un tipo de datos definido por el usuario en el servidor de bases de datos Informix.

Los tipos de datos de Informix-4GL se pueden clasificar en varias categorías, que son:

TEXT y BYTE son llamados tipos de datos largos.

ARRAY y RECORD tipos de datos estructurados o compuestos.

Y el resto son llamados tipos de datos simples. Dentro de estos se diferencias:

Tipos de datos tipo Carácter: CHAR(longitud), CHARACTER(longitud), y VARCHAR(longitud, mínimo reservado).

Tipos de dato tipo Fecha: DATE, DATETIME, INTERVAL.

Tipos de dato tipo Número: SMALLINT, INTEGER, INT, DECIMAL(precisión, escala), DEC(precisión, escala), NUMERIC(precisión, escala), MONEY(precisión, escala), FLOAT, DOUBLE PRECISION, SMALLFLOAT y REAL.

En la declaración de variables se puede usar la palabra reservada LIKE, lo cual permite declarar variables de forma más simple ya que el tipo de dato se especifica como una columna de la base de datos.

Page 19: IfxToJava2

19

EXPRESIONES 4GL

Una expresión 4GL es una secuencia de operandos, operadores y paréntesis que Informix-4GL puede evaluar como un valor simple. Sentencias, funciones, formatos de pantalla, operadores, y expresiones pueden tener expresiones como argumentos, componentes, u operandos. El contexto donde aparece una expresión así como su sintaxis determina el tipo de dato que esta retorna.

En base al tipo de dato que las expresiones retornan, éstas se clasifican en:

Booleanas Retorna TRUE o FALSE (o NULL en algunos contextos).

Integer Retorna un número entero de tipo INT o SMALLINT.

Number Retorna un valor de que puede ser de cualquier tipo de dato tipo Número.

Carácter Retorna un valor tipo: CHAR o VARCHAR.

Time Retorna un valor de tipo: DATE, DATETIME, o INTERVAL.

DIFERENCIAS ENTRE EXPRESIONES 4GL Y EXPRESIONES SQL

Las expresiones incluidas en sentencias SQL son evaluadas por el servidor de bases de datos y no por el interprete de Informix. El conjunto de operadores que pueden aparecen en las expresiones SQL se asemejan mucho al los que se pueden utilizar en 4GL pero no son idénticos.

Un programa 4GL puede incluir operadores 4GL, pero hay restricciones en las sentencias SQL. De igual manera muchos operadores SQL no son validos en expresiones 4GL.

Los siguientes operandos y operadores SQL no pueden aparecer en una expresión 4GL:

Identificadores SQL, tal como nombres de columnas de tablas o de bases de datos.

Las palabras reservadas de SQL: USER y ROWID.

Funciones agregadas que no tengan su par en las sentencias 4GL.

Los operadores BETWEEN e IN.

Las palabras reservada de expresiones SQL: EXIST, ALL, ANY, y SOME.

De igual modo tampoco se pueden incluir los siguientes operadores 4GL en expresiones SQL:

El operador aritmético de exponenciación (**) y de módulo (MOD).

Los operadores que actúan sobre cadenas: ASCII, COLUMN, SPACE, SPACES, y WORDWRAP.

Los operadores que actúan sobre campos: FIELD_TOUCHED(), GET_FLDBUF(), e INFIELD().

Los operadores de reports: LINENO, y PAGENO.

El operador TIME y DATE().

COMPONENTES DE LAS EXPRESIONES 4GL

Una expresión 4GL puede incluir los siguientes componentes:

Operadores.

Paréntesis para marcar una precedencia diferente de la que hay por defecto en los operadores.

Y operandos.

OPERADORES EN EXPRESIONES 4GL

Los operadores que se muestran en la siguiente tabla son los que pueden aparecen en las expresiones 4GL. Expresiones con varios operadores son evaluadas de acuerdo con su precedencia, de mayor (16) a menor (1) y asociatividad.

Page 20: IfxToJava2

20

Operador Descripción Asociatividad Precedencia

.

[ ]

( )

Elementos de un registro

Índice de arrays o subcadenas

Llamada a funciones

De izquierda

De izquierda

Ninguna

16

UNITS Cualificador simple de intervalos De izquierda 15

+

-

Mas unario

Menos unario

De derecha 14

**

MOD

Exponenciación

Módulo

De izquierda 13

*

/

Multiplicación

División

De izquierda 12

+

-

Suma

Resta

De izquierda

11

|| Concatenación De izquierda 10

LIKE

MATCHES

Comparación de Cadenas De derecha 9

<

<=

= ó ==

>=

>

!= ó <>

Menor que

Menor igual que

Igual que

Mayor igual que

Mayor que

Distinto

De izquierda 8

IN() Pertenencia a un conjunto De derecha 7

BETWEEN �. AND Rango De Izquierda 6

IS NULL Si es nulo De izquierda 5

NOT Negación lógica De izquierda 4

AND Intersección lógica De izquierda 3

OR Unión lógica De izquierda 2

ASCII

CLIPPED

COLUMN

ORD

SPACES

USING

Retorna el carácter ASCII

Borra caracteres blancos

Indica el inicio de la impresión

Retorna el código numérico de un ASCII

Inserta espacios en blanco

Formatea cadenas de caracteres

De derecha 1

Page 21: IfxToJava2

21

WORDWRAP Muestra texto en varias líneas

Tabla 4: Operadores de las expresiones 4GL

Aparte de lo anterior también son aplicables con mínima precedencia los siguientes operadores:

Operadores sobre campos: FIELD_TOUCHED(), GET_FLDBUF(), y INFIELD().

Operadores sobre reports: SPACE, LINENO y PAGENO.

Operadores de tiempo: CURRENT, DATE(), DAY(), EXTEND(), MDY(), MONTH(), TIME, TODAY, WEEKDAY(), y YEAR()

Muchos operadores 4GL no soportan operandos tipo RECORD o ARRAY, pero si aceptan como un operando una variable que sea un elemento de estos.

OPERANDOS EN EXPRESIONES 4GL

Los operandos en expresiones 4GL pueden ser uno de los siguientes:

Nombres de variables. Toda expresión 4GL puede contener el nombre de una variable de un tipo de dato simple o de constantes: TRUE, FALSE o NOTFOUND. Las variables también pueden ser un elemento simple de un registro o de un array.

Hay tres casos especiales en los cuales otros identificadores pueden ser operandos en expresiones 4GL: El atributo opcional COLOR en la especificación de pantallas, los operadores incorporados FIELD_TOUCHED(), GET_FLDBUF(), y INFIELD(), y los identificadores de tipo BYTE o TEXT como operandos de los operadores booleanos IS NULL e IS NOT NULL.

Si una variable es miembro de un registro se ha de cualificar ésta con el nombre del registro, como prefijo, separado por un punto (.).

Llamadas a funciones que retornen un único valor. Las expresiones pueden incluir llamadas a funciones que retornen única y exclusivamente un valor.

Las funciones pueden ser: definidas por el usuario o funciones incorporadas a condición de que retornen un valor simple de un tipo de dato valido.

Literales.

Cualquier otra expresión 4GL.

Dos expresiones no pueden aparecer consecutivamente sin algún separador, pero si se pueden anidar expresiones dentro de otras expresiones. En algunos contextos, sin embargo, la complejidad de las expresiones 4GL esta restringida.

TIPO DE EXPRESIONES

El tipo de dato de una expresión viene determinado por el tipo de dato que resulta de evaluar los operandos que intervienen en la misma. Así estos pueden ser:

EXPRESIONES BOOLEANAS

En 4GL una expresión booleana es aquella que retorna o bien TRUE (definido como 1) o FALSE (definido como 0) o en algunos contextos NULL. La sintaxis de las expresiones booleanas en sentencias 4GL no es idéntica a las condiciones booleanas en sentencias SQL.

En las expresiones booleanas pueden aparecer los siguientes operadores:

Los operadores lógicos: AND, OR y NOT que permiten combinar una o más expresiones booleanas en una expresión booleana simple.

Operadores booleanos que chequean operandos y retornar valores booleanos, como son:

Comparaciones de igualdad/desigualdad.

El operador IS NULL que examina valores nulos.

Page 22: IfxToJava2

22

Los operadores MATCHES o LIKE para comparar cadenas de caracteres.

El operador BETWEEN � AND que compara valores en un rango.

El operador IN() comprueba la pertenencia a un conjunto de elementos.

Cualquier tipo de expresión 4GL puede también ser una expresión booleana. Se puede usar una variable INT o SMALLINT para almacenar los valores retornados TRUE, FALSE o NULL.

Se pueden obtener resultados inesperados de una comparación booleana si los operandos son de distinto tipo de dato.

Las expresiones booleanas en las sentencias 4GL: CASE, IF, o WHILE retornarán FALSE si uno de los elementos de la comparación es NULL, exceptuando si son operandos de los operadores IS NULL o IS NOT NULL.

EXPRESIONES ENTERAS

Una expresión entera es aquella que retorna un número entero.

Las expresiones enteras pueden ser componentes de expresiones de cualquier otro tipo.

Seis operadores aritméticos pueden aparecer en una expresión entera, y deben tener expresiones enteras a ambos lados del operador, estos se muestran en la siguiente tabla:

Símbolo Nombre Nombre del Resultado Precedencia

** Exponenciación Potencia 12

Mod Módulo Resto entero 12

* Multiplicación Producto 11

/ División Cociente 11

+ Adición Suma 10

- Sustracción Diferencia 10

Tabla 5. Operadores sobre expresiones enteras

Todos los cálculos aritméticos son realizados después de convertir ambos operandos a un valor DECIMAL (aunque los operandos del operador MOD son convertidos primero a INTEGER).

Se pueden utilizar los operadores unarios: mas (+) y menos (-) a la izquierda una expresión para indicar el signo de la misma. Para los valores que no llevan signo, por defecto, se consideran en positivo (+). Se deben usar paréntesis para separar el operador de restar del operador unario menos, si estos van consecutivos como se muestra en el siguiente caso: minuendo - (- sustraendo).

Informix-4GL interpreta los dos menos consecutivos como un indicador de comentario.

EXPRESIONES DE TIPO NÚMERO

Una expresión tipo número es una especificación que evalúa un número real. Si un operando de una expresión de tipo número es el valor NULL, Informix-4GL evalúa la expresión completa al valor NULL. El rango de valores en una expresión de tipo número la fija el tipo de dato de la variable que recibe el resultado.

Los operadores aritméticos y operadores unarios que se aplican para enteros también son aplicables a expresiones tipo número.

EXPRESIONES TIPO CARÁCTER

Una expresión de tipo carácter es una especificación que evalúa cadenas de caracteres.

Page 23: IfxToJava2

23

Si una expresión tipo carácter incluye una variable 4GL o una función cuyo valor no es ni de tipo CHAR ni de tipo VARCHAR, 4GL intenta convertir el valor a una cadena de caracteres.

La longitud máxima de una cadena de caracteres es la aquella con la cual fue declarada. Los valores máximos son 32767 bytes para valores de tipo CHAR y 255 bytes para valores de tipo VARCHAR.

Si expresiones de tipo carácter son los operandos de un operador relacional, 4GL evalúa ambas expresiones de tipo carácter y luego compara los valores que retornan de acuerdo con su posición dentro de la secuencia natural.

Por defecto Informix-4GL considera los siguientes caracteres como imprimibles:

TAB (= CONTROL-I)

NEWLINE (= CONTROL-J)

FORMFEED (= CONTROL-L)

Y desde ASCII 32 (= blanco) hasta 128 (= ~)

Una cadena de caracteres que incluya uno o más caracteres no imprimibles puede ser un operando o el valor de retorno de una expresión de tipo carácter. Ésta puede ser almacenada en una variable 4GL o en una columna de la base de datos de tipo: CHAR, VARCAHR y TEXT.

EXPRESIONES DE TIPO TIEMPO

Una expresión tipo tiempo es una especificación de cómo Informix-4GL puede evaluar un valor de tipo DATE, DATETIME, o INTERVAL.

Estos tres tipos de datos están relacionados lógicamente porque ellos expresan valores en unidades de tiempo pero, a diferencia de los tipos de datos numéricos y tipo caracteres para los cuales Informix-4GL soporta conversiones automáticas de tipo (con sus posibles restricciones basadas en truncaciones o desbordamientos), las conversiones entre tipos de datos de tiempo son más limitadas. En un contexto donde una expresión de tipo tiempo es requerida, valores de tipo DATE o DATETIME pueden ser a menudo sustituidos unos por otros. Los valores de tipo INTERVAL, sin embargo, no pueden ser convertidos a valores tipo DATE o DATETIME.

Las expresiones de tiempo pueden ser operandos de algunos operadores aritméticos. Si el valor de retorno está dentro del rango de un tipo de dato DATE valido, la expresión retorna un valor tipo DATE.

Los operadores aritméticos que pueden operar sobre valores de tipo DATE son la adición y la sustracción, y los operadores de relación.

Page 24: IfxToJava2

24

TRADUCTOR DEL LENGUAJE Una vez definidas las características básicas del lenguaje, lo cual nos hace tener una somera idea sobre la complejidad del mismo, se continúa con la explicación de los elementos del traductor.

En esta sección se delimitar los prerrequisitos, alcance y enfoque que se va ha seguir dentro del proceso de traducción, se explica cada componente del traductor y como se enfocan los problemas planteados al traducir código fuente Informix-4GL a JAVA.

PRERREQUISITOS

Se parte de un código fuente escrito en Informix-4GL versión 4.16 y como especificación sintáctica se considerará esta versión del lenguaje aunque se han incorporado aquellas ampliaciones sintácticas producidas hasta versiones inferiores a la 6.0.

El traductor se ha desarrollado en JAVA y como versión mínima para compilar los fuentes del mismo es la versión JAVA 1.3. Se admiten versiones superiores a ésta. El programa ha sido probado también con las versiones 1.4 y 1.5 de forma satisfactoria.

El código objeto generado como resultado de la ejecución del traductor (.JAVA) necesita como mínimo la versión JAVA 1.3 para su compilación y ejecución.

ALCANCE Y LIMITACIONES

El traductor que se ha creado esta diseñado para reconocer la sintaxis completa de Informix-4GL e Informix-SQL. Para garantizar que el analizador sintáctico es correcto se probó sobre más de 1500 ficheros de código fuente con resultados satisfactorios.

Como él objetivo principal por el cual surge este proyecto es la reutilización de código fuente se parte de la premisa de que los ficheros fuentes contienen programas/módulos sintáctica y semánticamente correctos. Esto podría, erróneamente como se verá más adelante, llevar a pensar que los componentes de traductor se podrían ver reducidos en la parte correspondiente al analizador semántico, la utilización de la tabla de símbolos e incluso el manejo de errores.

Como limitaciones más importantes dentro de la parte 4GL de este traductor están: no se tratarán todas las sentencias del lenguaje y alguna de ellas con restricciones, y solo se considerarán los tipos de datos simples. Como este proyecto tiene dos partes diferenciadas y muy amplias: 4GL y SQL se ha decido limitar la parte del 4GL a aquellas sentencias básicas que permitan definir un programa, como contrapartida la parte SQL será estudiada en toda su profundidad y se aportarán en ella mejoras sustánciales respecto al lenguaje original. La sentencias 4GL que serán tratadas son:

Sentencias de definición de módulos: MAIN, END MAIN, FUNCTION, END FUNCTION, GLOBALS.

Sentencias de control de flujo: WHILE, FOR, FOREACH, CASE, RETURN, CONTINUE, IF, EXIT.

Sentencias de definición de variables: DEFINE, tipos de datos.

Sentencias 4GL puntuales: LET, CALL, DATABASE, WHENEVER.

Sentencia MENU.

El diseño del traductor sigue la metodología clásica: análisis descendente y traducción en un solo paso, aunque aportando características modernas como la aplicación del concepto: patrón estratégica a la hora de definir el generador de código. Así y de forma esquemática el traductor tiene los siguientes componentes:

Page 25: IfxToJava2

25

Figura 4: Componentes del traductor

A la hora de traducir código fuente se tendrá en cuenta para que gestor de bases de datos se esta generando el código objeto y en función de ello se instanciará el módulo de generación de código adecuado.

En las secciones siguientes se estudian cada una de las partes del traductor.

ANALIZADOR LEXICO

Dentro del analizador léxico hay pocos elementos que destacar. Como todo analizador léxico procesa el código fuente retornando tokens y diferenciando en estos entre los identificadores y las palabras reservadas.

Se ha de tener en cuenta que existen tokens que pueden ser al mismo tiempo identificador y palabra reservada. Esto ocurre, principalmente, porque dentro del lenguaje de programación Informix-4GL están embebidas las sentencias de Informix-SQL. Durante el análisis sintáctico se aplican reglas semánticas que permiten el uso de dichas palabras reservadas de Informix-SQL como identificadores de Informix-4GL al igual que en el lenguaje original. Algunas de estas palabras reservadas son: error, status, sqlca, sqlerrd, pageno, lineno, etc.

Las palabras reservadas de Informix-4GL se muestran en la figura siguiente:

Código fuente

Analizador Léxico

Analizador Sintáctico

Analizador Semántico

Tabla de Símbolos

Manejo de errores

Generación de Código

GI GD GO GS

CoI CoD CoO CoS

Código objeto dependiente

Page 26: IfxToJava2

26

Figura 5: Palabras reservadas de Informix

Cuando se inicializa el traductor se cargan las palabras reservadas de Informix en una tabla HASH de tal forma que durante el reconocimiento de los tokens se consulta en la misma si es una palabra reservada o por el contrario será: un identificador, una constante, un operador o un delimitador.

Los operadores que son reconocidos durante el análisis léxico se muestran en la siguiente tabla:

Operador Descripción

< menor que

<= menor igual que

= ó == igual que

> mayor que

absolute accept add after all allowing alter and any arg_val array arr_count arr_curr

asc ascii at attribute attributes audit auto average avg before begin between blink

blue bold border bottom break by call case char check clear clipped

close cluster columns command comment commit composites connect construct

continue count create current cyan database date datetime day dba decimal declare

default defaults defer define delete delimiter describe dim display displayonly distinct

double down downshift drop else end entry errorlog err_get err_print err_quit

escape every exclusive execute exists exit exitnow external false fetch field file finís

first float flush for foreach format from function globals goto grant green

group having headings help hour if immediate include incorrect index infield initialize

input insert instructions integer interrupt into invisible is joining key label last left

length let level like line lines load lock log long magenta main margin master

matches mdy message minute mode modify money month need netauf next

nextfield noentry not notfound noupdate null num_args on open option options

or order otherwise outer output page pause percent picture pipe prepare previous

print printer privileges program prompt public put queryclear quit record recover

register relative remove rename report required reslog resource return returning

reverse revoke right rollback rollforward row rows run screen scroll scr_line second

select serial set set_count share skip sleep smallint some space spaces sqlawarn sqlca

sqlcode sqlerrd start startlog statistics status step stop sum synonym table tables

then through thru time to today top trailer true type typedef underline union unique

unix unload unlock up update upshift user using validate value values verify

view wait waiting warning weekday when whenever where while white window with

without work wrap year yellow zerofill

Page 27: IfxToJava2

27

>= mayor igual que

<> ó != Desigualdad

|| Concatenación

* Multiplicación

/ División

- Resta

+ Suma

** Exponenciación

Tabla 6: Operadores reconocidos por el analizador léxico

Los comentarios del código fuente son ignorados a la hora de tratar los ficheros. Informix admite comentarios de línea, estas empieza por: # ó --, y comentarios de varias líneas, en este caso los bloques comentados están incluidos entre llaves: {}.

Durante el léxico también se reconocen las siguientes constantes:

Operador Descripción Ejemplos

entero número entero negativo o positivo

1, +54, -46

decimal número decimal 1.0, 1.3e+34, .32E-34, 43e+34

carácter carácter simple 'a'

cadena cadena de caracteres �cadena�

fecha fecha corta �dd/mm/yyyy�

fecha/hora fecha larga �yyyy-mm-dd hh:mm:ss.ffff�

Tabla 7: Constantes reconocidas por el analizador léxico

ANALISIS DE LA SINTAXIS

A continuación se detallan las producciones que definen la gramática de Informix y las cuales se reflejan en el analizador sintáctico del traductor creado.

<MÓDULO4GL> ::= <SENTENCIADATABASE> <GLOBALES> <VBLESBGLOBALES> <PROGRAMA> <SENTENCIADATABASE> ::= <VACIO> <SENTENCIADATABASE> ::= database <NOMBREDB> <ATRIBDB> <ATRIBDB> ::= <VACIO> <ATRIBDB> ::= exclusive <NOMBREDB> ::= <VARIABLE> <NOMBREDB> ::= <CTE_CADENA> <GLOBALES> ::= <VACIO> <GLOBALES> ::= <GLOBALS> <GLOBALS> ::= globals <RESTOGLOBALS> <RESTOGLOBALES> ::= <FICHERO> <RESTOGLOBALES> ::= <VBLES> end globals <VBLESGLOBALES> ::= <VACIO> <VBLESGLOBALES> ::= <VBLES> <PROGRAMA> ::= <PRIMSENT>

Page 28: IfxToJava2

28

<PRIMSENT> ::= <OTRASENT> <RESTOPROG> <PRIMSENT> ::= <SENTENCIAMAIN> <RESTOPROG> <RESTOPROG> ::= <VACIO> <RESTOPROG> ::= <OTRASENT> <RESTOPROG> <OTRASENT> ::= <SENTENCIAFUNCION> <OTRASENT> ::= <SENTENCIAREPORT> <SENTENCIAMAIN> ::= main <CUERPOMAIN> end main <CUERPOMAIN> ::= <VACIO> <CUERPOMAIN> ::= <SENTENCIADEFINE> <SENTENCIADATABASE> <SENTDELMAIN> <SENTDELMAIN> ::= <MASSENTDELMAIN> <MASSENTDELMAIN> ::= <VACIO> <MASSENTDELMAIN> ::= <UNASENTDELMAIN> <MASSENTDELMAIN> <UNASENTDELMAIN> ::= <SENTENCIA> <SENTENCIAFUCNION> ::= function <IDENTIFICADOR> <ARGUMENTOS> <CUERPOF> end function <CUERPOF> ::= <SENTENCIADEFINE> <SENTSDELAFUNCION> <SENTSDELAFUNCION> ::= VACIO> <SENTSDELAFUNCION> ::= <UNASENTDELAFUNCION> <SENTSDELAFUNCION> <UNASENTDELAFUNCION> ::= <SENTENCIA4GL> <UNASENTDELAFUNCION> ::= <SENTENCIASQL> <SENTENCIAREPORT> ::= report <IDENTIFICADOR> <ARGUMENTOS> <CUERPOR> end report <CUERPOP> ::= <SENTENCIADEFINE> <SECCOUTPUT> <SECCORDER> <SECCFORMAT> <SECCOUTPUT> ::= <VACIO> <SECCOUTPUT> ::= output <UNAOUTPUT> <MASOUTPUT> <MASOUTPUT> ::= <VACIO> <MASOUTPUT> ::= <UNAOUTPUT> <MASOUTPUT> <UNAOUTPUT> ::= report to <DESTREPORT> <UNAOUTPUT> ::= <PAGEDIMENSION> <DESTREPORT> ::= <CTE_CAD> <DESTREPORT> ::= printer <DESTREPORT> ::= screen <DESTREPORT> ::= file <CTE_CAD> <DESTREPORT> ::= pipe <OPCMODE> <STRINGOVBLE> <OPCMODE> ::= <VACIO> <OPCMODE> ::= in <RESTOOPCMODE> mode <RESTOOPCMODE> ::= line <RESTOOPCMODE> ::= form <PAGEDIMENSION> ::= page length <OPCIGUAL> <ENTERO> <PAGEDIMENSION> ::= top of page <OPCIGUAL> <CTE_CAD> <PAGEDIMENSION> ::= left margin <OPCIGUAL> <ENTERO> <PAGEDIMENSION> ::= top margin <OPCIGUAL> <ENTERO> <PAGEDIMENSION> ::= bottom margin <OPCIGUAL> <ENTERO> <PAGEDIMENSION> ::= right margin <OPCIGUAL> <ENTERO> <SECCORDER> ::= <VACIO> <SECCORDER> ::= order <EXTERNAL> by <ARGSORDER> <EXTERNAL> ::= <VACIO> <EXTERNAL> ::= external <ARGSORDER> ::= <IDENTIFICADOR> <MODARGSORDER> <MASARGSORDER> <MODARGSORDER> ::= <VACIO> <MODARGSORDER> ::= asc <MODARGSORDER> ::= desc <MASARGSORDER> ::= <VACIO> <MASARGSORDER> ::= <COMA> <ARGSORDER> <SECCFORMAT> ::= format <CUERPOFORMAT> <CUERPOFORMAT> ::= <EVERYROW> <CUERPOFORMAT> ::= <ELTOSFORMAT> <MASELTOSFORMAT> <EVERYROW> ::= every row <MASELTOSFORMAT>::= <VACIO> <MASELTOSFORMAT>::= <ELTOSFORMAT> <MASELTOSFORMAT> <ELTOSFORMAT> ::= <ELTOFORMAT> <SENTENCIASREPORT> <ELTOFORMAT> ::= <AFGERG>

Page 29: IfxToJava2

29

<ELTOFORMAT> ::= <BEFOREG> <ELTOFORMAT> ::= <FIRSTPAGE> <ELTOFORMAT> ::= <PAGEHEADER> <ELTOFORMAT> ::= <ONEVERYROW> <ELTOFORMAT> ::= <PAGETRAILER> <ELTOFORMAT> ::= <ONLASTROW> <AFTERG> ::= after group of <ARGUMENTOREPORT> <BEFOREG> ::= before group of <ARGUMENTOREPORT> <FIRSTPAGE> ::= first page header <PAGETRAILER> .:= page trailer <PAGEHEADER> .:= page header <ONEVERYROW> ::= on every row <SENTENCIADEFINE> ::= <VACIO> <SENTENCIADEFINE> ::= <VBLES> <VBLES> ::= <DEFVBLE> <MASDEFVBLES> <MASDEFVBLES> ::= <VACIO> <MASDEFVBLES> ::= <DEFVBLE> <MASDEFVBLES> <DEFVBLE> ::= define <DEFINICIONVBLES> <DEFINICIONVBLES> ::= <UNAVBLE> <OTRASVBLES> <TIPODATO> <MASVBLES> <MASVBLES> ::= <VACIO> <MASVBLES> ::= <COMA> <DEFINICIONVBLES> <UNAVBLE> ::= <IDENTIFICADOR> <OTRASVBLES>::= <VACIO> <OTRASVBLES>::= <COMA> <UNAVBLE> <OTRASVBLES> <TIPODATO> ::= <TIPODATOLIKE> <TIPODATO> ::= <TIPODATO4GL> <TIPODATOLIKE> ::= like <PROPIETARIO> <IDENTIFICADOR> <PTO> <IDENTIFICADOR> <PROPIETARIO> ::= <VACIO> <PROPIETARIO> ::= <IDENTIFICADOR> <PTO> <TIPODATO4GL> ::= <TIPOBASICO> <TIPODATO4GL> ::= <DARRAY> <TIPODATO4GL> ::= <DRECORD> <TIPODATO4GL> ::= byte <TIPODATO4GL> ::= text <TIPOBASICO> ::= char <RESTO1DIM> <TIPOBASICO> ::= character <RESTO1DIM> <RESTO1DIM> ::= <VACIO> <RESTO1DIM> ::= <PAR1> <NÚMERO> <PAR2> <TIPOBASICO> ::= int <TIPOBASICO> ::= integer <TIPOBASICO> ::= real <TIPOBASICO> ::= smallfloat <TIPOBASICO> ::= smallint <TIPOBASICO> ::= date <TIPOBASICO> ::= dec <RESTO2DIM> <TIPOBASICO> ::= decimal <RESTO2DIM> <TIPOBASICO> ::= numeric <RESTO2DIM> <RESTO2DIM> ::= <VACIO> <RESTO2DIM> ::= <PAR1> <NÚMERO> <SCALADEC> <PAR2> <SCALADEC> ::= <VACIO> <SCALADEC> ::= <COMA> <NÚMERO> <TIPOBASICO> ::= money <RESTO2DIM> <TIPOBASICO> ::= double precision <RESTO1DIM> <TIPOBASICO> ::= float <RESTO1DIM> <TIPOBASICO> ::= varchar <RESTO2DIM> <TIPOBASICO> ::= datetime <DATETIMEQUALIFIER> <TIPOBASICO> ::= interval <INTERVALQUALIFIER> <DRECORD> ::= record <RESTORECORD> <RESTORECORD>::= like <PROPIETARIO> <IDENTIFICADOR> <PTO> <ASTERISCO> <RESTORECORD>::= <DEFCAMPOSRECORD> end record <DEFCAMPOSRECORD> ::= <DEFINICIONVBLES> <DARRAY> ::= array <LEEDIMARRAY> of <NOARRAYTIPODATO> <LEEDIMARRAY> ::= COR1> <NÚMERO> <MASDIM> <COR2>

Page 30: IfxToJava2

30

<MASDIM> ::= <VACIO> <MASDIM> ::= <COMCA> <NÚMERO> <MASDIM> <NOARRAYTIPODATO> ::= <TIPOBASICO> <NOARRAYTIPODATO> ::= <DRECORD> <NOARRAYTIPODATO> ::= byte <NOARRAYTIPODATO> ::= text <DATETIMEQUALIFIER> ::= datetimequalifier <INTERVALQUALIFIER> ::= intervalqualifier <NÚMERO> ::= número <SCALDEC> ::= número <SENTENCIAS> ::= <SENTENCIA> <SENTENCIAS> <sENTENCIAS> ::= <VACIO> <SENTENCIA> ::= <SENTENCIA4GL> <SENTENCIA> ::= <SENTENCIASQL> <------------> <SENTENCIA4GL> ::= <SENTANCIACALL> <SENTENCIACALL> ::= call <IDENTIFICADOR> <PAR1> <ARGSLLAMADAF> <PAR2> <RESTOSENTENCIACALL> <RESTOSENTENCIACALL> ::= <VACIO> <RESTOSENTENCIACALL> ::= returning <VBLESRECIBERDO> <ARGSLLAMADAF> ::= <VACIO> <ARGSLLAMADAF> ::= <EXPR4GL> <MASARGSLLAMADAF> <MASARGSLLAMADAF> ::= <VACIO> <MASARGSLLAMADAF> ::= <COMA> <EXPR4GL> MASARGSLLAMADAF> <SENTENCIA4GL> ::= <SENTENCIACASE> <SENTENCIACASE> ::= case <CRITERIOCASE> <OTHERWISEBLOCK> end case <CRITERIOCASE> ::= <CRITERIOCASEMULTIPLE> <CRITERIOCASE> ::= <CRITERIOCASESIMPLE> <CRITERIOCASESIMPLE> ::= <EXPR4GL> <WHENSIMPLE> <CRITERIOCASESIMPLE> ::= <PAR1> <EXPR4GL> <PAR2> <WHENSIMPLE> <CRITERIOCASEMULTIPLE> ::= when <EXPRBOOL> <SENTDELCASE> <MASWHENMULTIPLE> <MASWHENMULTIPLE> ::= <VACIO> <MASWHENMULTIPLE> ::= when <EXPRBOOL> <SENTDELCASE> <MASWHENMULTIPLE> <WHENSIMPLE> ::= when <EXPR4GL> <SENTDELCASE> <MASWHENSIMPLE> <MASWHENSIMPLE> ::= <VACIO> <MASWHENSIMPLE> ::= when <EXPR4GL> <SENTDELCASE> <MASWHENSIMPLE> <OTHERWISEBLOCK> ::= otherwise SENTDELCASE> <SENTDELCASE> ::= <UNASENTDELCASE> <MASSENTDELCASE> <MASSENTDELCASE> ::= <VACIO> <MASSENTDELCASE> ::= <UNASENTDELCASE> <MASSENTDELCASE> <UNASENTDELCASE> ::= <SENTENCIA> <SENTENCIA4GL> ::= <SENTENCIACLEAR> <SENTENCIACLEAR> ::= clear form <SENTENCIACLEAR> ::= clear window <IDENTIFICADOR> <SENTENCIACLEAR> ::= clear window screen <SENTENCIACLEAR> ::= clear screen <SENTENCIACLEAR> ::= clear <CLAUSULASCAMPO> <SENTENCIA4GL> ::= <SENTENCIACLOSE> <SENTENCIACLOSE> ::= close form <IDENTIFICADOR> <SENTENCIACLOSE> ::= close window <IDENTIFICADOR> <SENTENCIA4GL> ::= <SENTENCIACONSTRUCT> <SENTENCIACONSTRUCT> ::= construct <CONSTRUCTVBLE> <OPCIONALCONSTRUCT> <OPCIONALCONSTRUCT> ::= <ATRIBUTECLAUSE> <HELP> <CONSTRUCTBLOCK> <CONSTRUCTVBLE> ::= <VARIABLE> on <COLUMNLIST> from <CLAUSUSLACAMPO> <CONSTRUCTVBLE> ::= by name <VARIABLE> on <COLUMNLIST> <CONSTRUCTBLOCK> ::= <VACIO> <CONSTRUCTBLOCK> ::= <UNCONSTRUCTBLOCK> <MASCONSTRUCTBLOCK> end construct <MASCONSTRUCTBLOCK> ::= <VACIO>

Page 31: IfxToJava2

31

<MASCONSTRUCTBLOCK> ::= <UNCONSTRUCTBLOCK> <MASCONSTRUCTBLOCK> <UNCONSTRUCTBLOCK> ::= before <MASBEFOREAFTERCONSTRUCTBLOCK> <SENTDELCONSTRUCT> <UNCONSTRUCTBLOCK> ::= after <MASBEFOREAFTERCONSTRUCTBLOCK> <SENTDELCONSTRUCT> <UNCONSTRUCTBLOCK> ::= on key <PARAMETROSONKEY> <SENTDELCONSTRUCT> <MASBEFOREAFTERCONSTRUCTBLOCK> ::= construct <MASBEFOREAFTERCONSTRUCTBLOCK> ::= field <CAMPOS> <SENTDELCONSTRUCT> ::= <UNASENTDELCONTRUCT> <MASSENTENCIASDELCONSTRUCT> <MASSENTENCIASDELCONSTRUCT> ::= <VACIO> <MASSENTENCIASDELCONSTRUCT> ::= <UNASENTDELCONTRUCT> <MASSENTENCIASDELCONSTRUCT> <UNASENTDELCONTRUCT> ::= <SENTENCIA> <UNASENTDELCONTRUCT> ::= <SENTNEXTFIELDCONSTRUCT> <SENTNEXTFIELDCONSTRUCT> ::= next field <NEXTFIELDCONSTRUCT> <NEXTFIELDCONSTRUCT> ::= previos <NEXTFIELDCONSTRUCT> ::= next <NEXTFIELDCONSTRUCT> ::= <CLAUSULACAMPO> <SENTENCIA4GL> ::= <SENTENCIACONTINUE> <SENTENCIACONTINUE> ::= continue <PALRESCONTINUE> <SENTENCIA4GL> ::= <SENTENCIACURRENT> <SENTENCIACURRENT> ::= current window is <RESTOSENTENCIACURRENT> <RESTOSENTENCIACURRENT> ::= screen <RESTOSENTENCIACURRENT> ::= <IDENTIFICADOR> <SENTENCIA4GL> ::= <SENTENCIADATABASE> <SENTENCIA4GL> ::= <SENTENCIADEFINE> <SENTENCIA4GL> ::= <SENTENCIADISPLAY> <SENTENCIADISPLAY> ::= display <RESTOSENTENCIADISPLAY> <RESTOSENTENCIADISPLAY> ::= by name <LISTADEVBLES> <ATTRIBUTECLAUSE> <RESTOSENTENCIADISPLAY> ::= <EXPRS> <MASSENTENCIADISPLAY> <MASSENTENCIADISPLAY> ::= at <EXPRINT> <COMA> <EXPRINT> <ATTRIBUTECLAUSE> <MASSENTENCIADISPLAY> ::= to <CLAUSULASCAMPO> <ATTRIBUTECLAUSE> <RESTOSENTENCIADISPLAY> ::= form <IDENTIFICADOR> <ATTRIBUTECLAUSE> <RESTOSENTENCIADISPLAY> ::= array <IDENTIFICADOR> to <IDENTIFICADOR> <PTO> <ASTERISCO> <RESTODISPLAYARRAY> <RESTODISPLAYARRAY> ::= <ATTRIBUTECLAUSE> <LASTDISPLAYARRAY> <LASTDISPLAYARRAY> ::= <VACIO> <LASTDISPLAYARRAY> ::= end display <LASTDISPLAYARRAY> ::= <ONKEYBLOCK> end display <ONKEYBLOCK> ::= on key <PARAMETROSONKEY> <SENTDELONKEY> <SENTDELDISPLAYARRAY> ::= <UNASENTDELDISPLAYARRAY> <MASSENTDELDISPLAYARRAY> <MASSENTDELDISPLAYARRAY> ::= <VACIO> <MASSENTDELDISPLAYARRAY> ::= <UNASENTDELDISPLAYARRAY> <MASSENTDELDISPLAYARRAY> <UNASENTDELDISPLAYARRAY> ::= <SENTENCIA> <SENTENCIA4GL> ::= <SENTENCIAERROR> <SENTENCIAERROR> ::= error <EXPRS> <ATTRIBUTECLAUSE> <SENTENCIA4GL> ::= <SENTENCIAEXIT> <SENTENCIAEXIT> ::= exit <RESTOSENTEXITP> <RESTOSENTEXITP> ::= case <RESTOSENTEXITP> ::= construct <RESTOSENTEXITP> ::= display <RESTOSENTEXITP> ::= for <RESTOSENTEXITP> ::= foreach <RESTOSENTEXITP> ::= input <RESTOSENTEXITP> ::= menu <RESTOSENTEXITP> ::= report <RESTOSENTEXITP> ::= prompt <RESTOSENTEXITP> ::= while

Page 32: IfxToJava2

32

<RESTOSENTEXITP> ::= program <RESTOEXITPROGRAM> <RESTOEXITPROGRAM> ::= <VACIO> <RESTOEXITPROGRAM> ::= <PAR1> <EXPRINT> <PAR2> <RESTOEXITPROGRAM> ::= <EXPRINT> <SENTENCIA4GL> ::= <SENTENCIAFINISHREPORT> <SENTENCIAFINISHREPORT> ::= finish report <IDENTIFICADOR> <SENTENCIA4GL> ::= <SENTENCIAFOR> <SENTENCIAFOR> ::= for <VARIABLE> <IGUAL> <EXPRINT> to <EXPRINT> <OPCINCFOR> <SENTDELFOR> end for <OPCINCFOR> ::= <VACIO> <OPCINCFOR> ::= step <EXPRINT> <SENTDELFOR> ::= <UNASENTDELFOR> <MASSENTDELFOR> <MASSENTDELFOR> ::= <VACIO> <MASSENTDELFOR> ::= <UNASENTDELFOR> <MASSENTDELFOR> <UNASENTDELFOR> ::= <SENTENCIA4GL> <UNASENTDELFOR> ::= <SENTENCIASQL> <SENTENCIA4GL> ::= <SENTENCIAFOREACH> <SENTENCIAFOREACH> ::= foreach <IDENTIFICADOR> <OPCINTOFOREACH> <SENTDELFOREACH> end foreach <OPCINTOFOREACH> ::= into <LISTADEVBLES> <OPCINTOFOREACH> ::= <VACIO> <SENTDELFOREACH> ::= <UNASENTDELFOREACH> <MASSENTDELFOREACH> <MASSENTDELFOREACH> ::= <VACIO> <MASSENTDELFOREACH> ::= <SENTDELFOREACH> <UNASENTDELFOREACH> ::= <SENTENCIASQL> <UNASENTDELFOREACH> ::= <SENTENCIA4GL> <SENTENCIA4GL> ::= <SENTENCIAGOTO> <SENTENCIAGOTO> ::= goto <OPCDOSPTOSGOTO> <IDENTIFICADOR> <OPCDOSPTOSGOTO> ::= <VACIO> <OPCDOSPTOSGOTO> ::= <DOSPTOS> <SENTENCIA4GL> ::= <SENTENCIAIF> <SENTENCIAIF> ::= if <EXPRBOOL> then <SENTDELIF> <OPCELSEIF> end if <OPCELSEIF> ::= <VACIO> <OPCELSEIF> ::= else <SENTDELIF> <SENTDELIF> ::= <VACIO> <SENTDELIF> ::= <UNASENTDELIF> <MASSENTDELIF> <MASSENTDELIF> ::= <VACIO> <MASSENTDELIF> ::= <SENTDELIF> <UNASENTDELIF> ::= <SENTENCIA4GL> <UNASENTDELIF> ::= <SENTENCIASQL> <SENTENCIA4GL> ::= <SENTENCIAINITIALIZE> <SENTENCIAINITIALIZE> ::= initialize <LISTADEVBLES> <RESTOINITIALIZE> <RESTOINITIALIZE> ::= to null <RESTOINITIALIZE> ::= like <RESTOLIKEINITIALIZE> <RESTOLIKEINITIALIZE> ::= <UNARESTOLIKEINITIALIZE> <MASRESTOLIKEINITIALIZE> <MASRESTOLIKEINITIALIZE> ::= <VACIO> <MASRESTOLIKEINITIALIZE> ::= <COMA> <UNARESTOLIKEINITIALIZE> <MASRESTOLIKEINITIALIZE> <UNARESTOLIKEINITIALIZE> ::= <PROPIETARIO> <IDENTIFICADOR> <PTO> <ULTUNARESTOLIKEINITIALIZE> <ULTUNARESTOLIKEINITIALIZE> ::= <IDENTIFICADOR> <ULTUNARESTOLIKEINITIALIZE> ::= <ASTERISCO> <SENTENCIA4GL> ::= <SENTENCIAINPUT> <SENTENCIAINPUT> ::= input <INPUTARRAYONO> <INPUTARRAYONO> ::= <BINDINGCLAUSE> <ATTRIBUTECLAUSE> <HELP> <INPUTBLOCK> <BINDINGCLAUSE> ::= by name <LISTDEAVBLES> <OPCWITHOUTDEFAULTS>

Page 33: IfxToJava2

33

<BINDINGCLAUSE> ::= <LISTADEVBLES> <OPCWITHOUTDEFAULTS> from <CLAUSULASCAMPO> <OPCWITHOUTDEFAULTS> ::= <VACIO> <OPCWITHOUTDEFAULTS> ::= without defaults <INPUTBLOCK> ::= <VACIO> <INPUTBLOCK> ::= <UNAINPUTBLOCK> <MASINPUTBLOCK> end input <MASINPUTBLOCK> ::= <VACIO> <MASINPUTBLOCK> ::= <UNINPUTBLOCK> <MASINPUTBLOCK> <UNAINPUTBLOCK> ::= <PARTE1INPUTBLOCK> <PARTE2INPUTBLOCK> <PARTE1INPUTBLOCK> ::= before <RESTOPARTE1INPUTBLOCK> <PARTE1INPUTBLOCK> ::= after <RESTOPARTE1INPUTBLOCK> <PARTE1INPUTBLOCK> ::= on key <PARAMETROSONKEY> <RESTOPARTE1INPUTBLOCK> ::= field <CLAUSULASCAMPO> <RESTOPARTE1INPUTBLOCK> ::= input <PARTE2DELINPUTBLOCK> ::= <VACIO> <PARTE2DELINPUTBLOCK> ::= <SENTDELINPUTBLOCK> <SENTDELINPUTBLOCK> ::= <UNASENTDELINPUTBLOCK> <MASSENTDELINPUTBLOCK> <MASSENTDELINPUTBLOCK> ::= <VACIO> <MASSENTDELINPUTBLOCK> ::= <UNASENTDELINPUTBLOCK> <MASSENTDELINPUTBLOCK> <UNASENTDELINPUTBLOCK> ::= <SENTENCIA4GL> <UNASENTDELINPUTBLOCK> ::= <SENTENCIASQL> <UNASENTDELINPUTBLOCK> ::= <SENTNEXTFIELDINPUTBLOCK> <SENTNEXTFIELDINPUTBLOCK> ::= next field <NEXTFIELDINPUTBLOCK> <NEXTFIELDINPUTBLOCK> ::= next <NEXTFIELDINPUTBLOCK> ::= previos <NEXTFIELDINPUTBLOCK> ::= <IDENTIFICADOR> <INPUTARRAYONO> ::= array <BINDINGARRAYCLAUSE> <ATTRIBUTECLAUSE> <HELP> <INPUTARRAYBLOCK> <BINDINGARRAYCLAUSE> ::= <IDENTIFICADOR> <OPCWITHOUTDEFAULTS> from <IDENTIFICADOR> <PTO> <ASTERISCO> <INPUTARRAYBLOCK> ::= <UNAINPUTARRAYBLOCK> <MASINPUTARRAYBLOCK> end input <MASINPUTARRAYBLOCK> ::= <VACIO> <MASINPUTARRAYBLOCK> ::= <UNINPUTARRAYBLOCK> <MASINPUTARRAYBLOCK> <UNAINPUTARRAYBLOCK> ::= <PARTE1INPUTARRAYBLOCK> <PARTE2DELINPUTARRAYBLOCK> <PARTE1INPUTARRAYBLOCK> ::= before <RESTOPARTE1INPUTBLOCK> <PARTE1INPUTARRAYBLOCK> ::= after <RESTOPARTE1INPUTBLOCK> <PARTE1INPUTARRAYBLOCK> ::= on key <PARAMETROSONKEY> <RESTOPARTE1INPUTARRAYBLOCK> ::= field <CLAUSULASCAMPO> <RESTOPARTE1INPUTARRAYBLOCK> ::= input <RESTOPARTE1INPUTARRAYBLOCK> ::= delete <RESTOPARTE1INPUTARRAYBLOCK> ::= insert <RESTOPARTE1INPUTARRAYBLOCK> ::= row <PARTE2DELINPUTARRAYBLOCK> ::= <VACIO> <PARTE2DELINPUTARRAYBLOCK> ::= <SENTDELINPUTARRAYBLOCK> <SENTDELINPUTARRAYBLOCK> ::= <UNASENTDELINPUTARRAYBLOCK> <MASSENTDELINPUTARRAYBLOCK> <MASSENTDELINPUTARRAYBLOCK> ::= <VACIO> <MASSENTDELINPUTARRAYBLOCK> ::= <UNASENTDELINPUTARRAYBLOCK> <MASSENTDELINPUTARRAYBLOCK> <UNASENTDELINPUTARRAYBLOCK> ::= <SENTENCIA4GL> <UNASENTDELINPUTARRAYBLOCK> ::= <SENTENCIASQL> <UNASENTDELINPUTARRAYBLOCK> ::= <SENTNEXTFIELDINPUTBLOCK> <SENTNEXTFIELDINPUTBLOCK> ::= next field <NEXTFIELDINPUTBLOCK> <NEXTFIELDINPUTARRAYBLOCK> ::= next <NEXTFIELDINPUTARRAYBLOCK> ::= previos <NEXTFIELDINPUTARRAYBLOCK> ::= <CLAUSULACAMPO> <sENTENCIA4GL> ::= <SENTENCIALABEL> <SENTENCIALABEL> ::= label <IDENTIFICADOR> <DOSPTOS> <sENTENCIA4GL> ::= <SENTENCIALET> <SENTENCIALET> ::= let <RESTOSENTENCIALET> <RESTOSENTENCIALET> ::= <IDENTIFICADOR> <PTO> <ASTERISCO> <IGUAL> <IDENTIFICADOR> <PTO> <ASTERISCO>

Page 34: IfxToJava2

34

<RESTOSENTENCIALET> ::= <VBLERECIBERDO> <IGUAL> <RESTOSENTLET> <RESTOSENTLET> ::= null <RESTOSENTLET> ::= <EXPRS4GL> <sENTENCIA4GL> ::= <SENTENCIALOCATE> <SENTENCIALOCATE> ::= locate <LISTADEVBLES> in <RESTOLOCATE> <RESTOLOCATE> ::= memory <RESTOLOCATE> ::= file <RESTOFILELOCATE> <RESTOFILELOCATE> ::= <VACIO> <RESTOFILELOCATE> ::= <CTE_CAD> <RESTOFILELOCATE> ::= <VARIABLE> <sENTENCIA4GL> ::= <SENTENCIAMENU> <SENTENCIAMENU> ::= menu <STRINGOVBLE> <MENUCONTROLBLOCK> end menu <MENUCONTROLBLOCK> ::= <UNMENUCONTROLBLOCK> <MASMENUCONTROLBLOCK> <MASMENUCONTROLBLOCK> ::= <VACIO> <MASMENUCONTROLBLOCK> ::= <UNMENUCONTROLBLOCK> <MASMENUCONTROLBLOCK> <UNMENUCONTROLBLOCK> ::= <PARTE1MENUCONTROLBLOCK> <SENTDELMENU> <PARTE1MENUCONTROLBLOCK> ::= before menu <PARTE1MENUCONTROLBLOCK> ::= command <COMMANDBLOCK> <COMMANDBLOCK> ::= <OPCKEYMENU> <MASOPCKEYMENU> <COMMANDBLOCK> ::= <MASCOMMANDBLOCK> <MASOPCKEYMENU> ::= <VACIO> <MASOPCKEYMENU> ::= <MASCOMMANDBLOCK> <MASCOMMANDBLOCK> ::= <STRINGOVBLE> <OPCSTRINGOVBLE> <HELP> <OPCKEYMENU> ::= key <PARAMETROSONKEYMENU> <SENTDELMENUCONTROLBLOCK> ::= <UNASENTDELMENUCONTROLBLOCK> <MASSENTDELMENUCONTROLBLOCK> <MASSENTDELMENUCONTROLBLOCK> ::= <VACIO> <MASSENTDELMENUCONTROLBLOCK> ::= <SENTDELMENU> <UNASENTDELMENUCONTROLBLOCK> ::= next option <STRINGOVBL> <UNASENTDELMENUCONTROLBLOCK> ::= show <RESTOSHOWHIDEMENU> <UNASENTDELMENUCONTROLBLOCK> ::= hide <RESTOSHOWHIDEMENU> <UNASENTDELMENUCONTROLBLOCK> ::= <SENTENCIA4GL> <UNASENTDELMENUCONTROLBLOCK> ::= <SENTENCIASQL> <RESTOSHOWHIDEMENU> ::= option <MASRESTOSHOWHIDEMENU> <MASRESTOSHOWHIDEMENU> ::= all <MASRESTOSHOWHIDEMENU> ::= <STRINGSOVBLES> <sENTENCIA4GL> ::= <SENTENCIAMESSAGE> <SENTENCIAMESSAGE> ::= message <STRINGSOVBLES> <ATRIBUTECLAUSE> <sENTENCIA4GL> ::= <SENTENCIANEED> <SENTENCIANEED> ::= need <EXPRINT> lines <sENTENCIA4GL> ::= <SENTENCIAOPEN> <SENTENCIAOPEN> ::= open <RESTOSENTOPEN> <RESTOSENTOPEN> ::= form <IDENTIFICADOR> from <STRINGOVBLE> <RESTOSENTOPEN> ::= window at <EXPRINT> <COMA> <EXPRINT> with <RESTOOPENWINDOW> <OPENWINDOWATTRIBUTECLAUSE> <RESTOOPENWINDOW> ::= form <STRINGOVBLE> <RESTOOPENWINDOW> ::= <EXPRINT> rows <COMA> <EXPRINT> columns <sENTENCIA4GL> ::= <SENTENCIAOPTIONS> <SENTENCIAOPTIONS> ::= options <RESTOSENTOPTIONS> <RESTOSENTOPTIONS> ::= <UNASENTOPTIONS> <MASSENTOPTIONS> <MASSENTOPTIONS> ::= <VACIO> <MASSENTOPTIONS> ::= <COMA> <UNASENTOPTIONS> <MASSENTOPTIONS> <UNASENTOPTIONS> ::= comment <RESTO1UNASENTOPTIONS> <UNASENTOPTIONS> ::= error <RESTO1UNASENTOPTIONS> <UNASENTOPTIONS> ::= form <RESTO1UNASENTOPTIONS> <UNASENTOPTIONS> ::= menu <RESTO1UNASENTOPTIONS> <UNASENTOPTIONS> ::= message <RESTO1UNASENTOPTIONS> <UNASENTOPTIONS> ::= prompt <RESTO1UNASENTOPTIONS>

Page 35: IfxToJava2

35

<RESTO1UNASENTOPTIONS> ::= line <RESERVEDLINEPOSITION> <UNASENTOPTIONS> ::= accept <RESTO2UNASENTOPTIONS> <UNASENTOPTIONS> ::= delete <RESTO2UNASENTOPTIONS> <UNASENTOPTIONS> ::= insert <RESTO2UNASENTOPTIONS> <UNASENTOPTIONS> ::= next <RESTO2UNASENTOPTIONS> <UNASENTOPTIONS> ::= previous <RESTO2UNASENTOPTIONS> <RESTO2UNASENTOPTIONS> ::= key <KEYPARAM> <UNASENTOPTIONS> ::= help <RESTO3UNASENTOPTIONS> <RESTO3UNASENTOPTIONS> ::= <RESTO2UNASENTOPTIONS> <RESTO3UNASENTOPTIONS> ::= file <CTE_CAD> <UNASENTOPTIONS> ::= display attribute <OPTIONSATRIBUTECLAUSE> <UNASENTOPTIONS> ::= input <RESTO4UNASENTOPTIONS> <RESTO4UNASENTOPTIONS> ::= wrap <RESTO4UNASENTOPTIONS> ::= no wrap <RESTO4UNASENTOPTIONS> ::= attribute <ATRIBUTECLAUSEOPTIONS> <UNASENTOPTIONS> ::= file order <RESTO5UNASENTOPTIONS> <RESTO5UNASENTOPTIONS> ::= unconstrained <RESTO5UNASENTOPTIONS> ::= constrained <UNASENTOPTIONS> ::= sql interrupt <RESTO6UNASENTOPTIONS> <RESTO6UNASENTOPTIONS> ::= on <RESTO6UNASENTOPTIONS> ::= off <sENTENCIA4GL> ::= <SENTENCIAOUTPUTTOREPORT> <SENTENCIAOUTPUTTOREPORT> ::= output to report <IDENTIFICADOR> <PAR1> <ARGSOUTPUTTOREPROT> <PAR2> <ARGSOUTPUTTOREPORT> ::= <VACIO> <ARGSOUTPUTTOREPORT> ::= <EXPR4GL> <MASARGSOUTPUTTOREPORT> <MASARGSOUTPUTTOREPORT> ::= <VACIO> <MASARGSOUTPUTTOREPORT> ::= <COMA> <EXPR4GL> <MASARGSOUTPUTTOREPORT> <SENTENCIAPRINT> ::= print <RESTOPRINT> <RESTOPRINT> ::= <VACIO> <RESTOPRINT> ::= file <CTE_CAD> <RESTOPRINT> ::= <OTROSELTOSRESTOPRINT> <FINRESTOPRINT> <FINRESTOPRINT> ::= <VACIO> <FINRESTOPRINT> ::= <PTOYCOMA> <OTROSELTOSRESTOPRINT> ::= <ELTORESTOPRINT> <MASOTROSELTOSRESTOPRINT> <MASOTROSELTOSRETOPRINT> ::= <VACIO> <MASOTROSELTOSRETOPRINT> ::= <COMA> <ELTORESTOPRINT> <MASOTROSELTOSRESTOPRINT> <ELTORESTOPRINT> ::= byte <VARIABLE> <ELTORESTOPRINT> ::= text <VARIABLE> <OPCWORDWRAP> <ELTORESTOPRINT> ::= <EXPR> <RESTOOPCWORDWRAP> <OPCWORDWRAP> ::= <VACIO> <OPCWORDWRAP> ::= wordwrap <RESTOOPCWORDWRAP> <RESTOOPCWORDWRAP> ::= right margin <EXPRINT> <RESTOOPCWORDWRAP> ::= <VACIO> <OPCWORDWRAP> ::= <VACIO> <OPCWORDWRAP> ::= wordwrap <RESTOOPCWORDWRAP> <RESTOOPCWORDWRAP> ::= right margin <EXPRINT> <RESTOOPCWORDWRAP> ::= <VACIO> <sENTENCIA4GL> ::= <SENTENCIAPROMPT> <SENTENCIAPROMPT> ::= prompt <STRINGSOVBLES> <ATTRIBUTECLAUSE> for <OPCCHAR> <VBLERECIBERDO> <HELP> <ATTRIBUTECLAUSE> <RESTOSENTPROMPT> <RESTSENTPROMPT> ::= <VACIO> <RESTSENTPROMPT> ::= <ONKEYPROMPT> end prompt <ONKEYPROMPT> ::= <UNAONKEYPROMPT> <MASONKEYPROMPT> <MASONKEYPROMPT> ::= <VACIO> <MASONKEYPROMPT> ::= <UNAONKEYPROMPT> <MASONKEYPROMPT> <UNAONKEYPROMPT> ::= on key <PARAMETROSONKEY> <SENTDELPROMPT> <SENTDELPROMPT> ::= <UNASENTDELPROMPT> <MASSENTDELPROMPT> <MASSENTDELPROMPT> ::= <VACIO> <MASSENTDELPROMPT> ::= <SENTDELPROMPT> <UNASENTDELPROMPT> ::= <SENTENCIA>

Page 36: IfxToJava2

36

<SENTENCIA4GL> ::= <SENTENCIARETURN> <SENTENCIARETURN> ::= return <EXPRS4GL> <sENTENCIA4GL> ::= <SENTENCIARUN> <SENTENCIARUN> ::= run <STRINGOVBLE> <RESTOSENTRUN> <RESTOSENTRUN> ::= returning <VBLERECIBERDO> <RESTOSENTRUN> ::= without waiting <sENTENCIA4GL> ::= <SENTENCIASCROLL> <SENTENCIASCROLL> ::= scroll <CLAUSUSLACAMPO> <UPODOWNSCROLL> <OPCBYSCROLL> <UPODOWNSCROLL> ::= up <UPODOWNSCROLL> ::= down <OPCBYSCROLL> ::= <VACIO> <OPCBYSCROLL> ::= by <INTEGEROVBLE> <sENTENCIA4GL> ::= <SENTENCIASLEEP> <SENTENCIASLEEP> ::= sleep <EXPRINT> <sENTENCIA4GL> ::= <SENTENCIASTARTREPORT> <SENTENCIASTARTREPORT> ::= start report <IDENTIFICADOR> <RESTOSTARTREPROT> <RESTOSTARTREPORT> ::= <OPCTOCLAUSE> <OPCWITHDIMENSIONS> <OPCTOCLAUSE> ::= <VACIO> <OPCTOCLAUSE> ::= to <DESTINOSREPORT> <DESTINOSREPORT> ::= <DESTINOREPORT> <DESTINOSREPORT> ::= output <MASDESTINOREPOT> <MASDESTINOREPOT> ::= <STRINGOVBLE> <OPCRESTODESTINOREPORT> <OPCRESTODESTINOREPORT> ::= <VACIO> <OPCRESTODESTINOREPORT> ::= destination <STRINGOVBLE> <PAGEDIMENSIONS> ::= <PAGEDIMENSION> <MASPAGEDIMENSIONS> <MASPAGEDIMENSIONS> ::= <VACIO> <MASPAGEDIMENSIONS> ::= <COMA> <PAGEDIMENSION> <MASPAGEDIMENSIONS> <sENTENCIA4GL> ::= <SENTENCIASQLEXEC> <SENTENCIASQLEXEC> ::= sql <SENTENCIASSQL> <OPCPTOYCOMA> end sql <OPCPTOYCOMA> ::= <VACIO> <OPCPTOYCOMA> ::= <PTOYCOMA> <sENTENCIA4GL> ::= <SENTENCIATERMINATE> <SENTENCIATERMINATE> ::= terminate report <IDENTIFICADOR> <SENTENCIA4GL> ::= <SENTENCIAUNLOAD> <SENTENCIAUNLOAD> ::= unload to <STRINGOVBLE> <OPCDELIMITER> <RESTOSENTUNLOAD> <RESTOSENTUNLOAD> ::= <SENTENCIASELECT> <RESTOSENTUNLOAD> ::= <VARIABLE> <sENTENCIA4GL> ::= <SENTENCIAVALIDATE> <SENTENCIAVALIDATE> ::= validate <LISTADEVBLES> like <RESTOVALIDATE> <RESTOVALIDATE> ::= <UNARESTOVALIDATE> <MASRESTOVALIDATE> <MASRESTOVALIDATE> ::= <VACIO> <MASRESTOVALIDATE> ::= <COMA> <UNARESTOVALIDATE> <MASRESTOVALIDATE> <UNARESTOVALIDATE> ::= <PROPIETARIO> <IDENTIFICADOR> <PTO> <RESTOUNAVALIDATE> <RESTOUNAVALIDATE> ::= <ASTERISCO> <RESTOUNAVALIDATE> ::= <IDENTIFICADOR> <sENTENCIA4GL> ::= <SENTENCIAWHENEVER> <SENTENCIAWHENEVER> ::= whenever <PARTE1WHENEVER> <PARTE2WHENEVER> <PARTE1WHENEVER> ::= not found <PARTE1WHENEVER> ::= <PARTE1ERRORWHENEVER><PARTE2ERRORWHENEVER> <PARTE1WHENEVER> ::= warning <PARTE1WHENEVER> ::= sqlwarning <PARTE1ERRORWHENEVER> ::= <VACIO> <PARTE1ERRORWHENEVER> ::= any <PARTE2ERRORWHENEVER> ::= sqlerror

Page 37: IfxToJava2

37

<PARTE2ERRORWHENEVER> ::= error <PARTE2WHENEVER> ::= continue <PARTE2WHENEVER> ::= stop <PARTE2WHENEVER> ::= call <IDENTIFICADOR> <PARTE2WHENEVER> ::= <PARTE1GOTOWHENEVER> <PARTE2GOTOWHENEVER> <PARTE1GOTOWHENEVER> ::= go to <PARTE1GOTOWHENEVER> ::= goto <PARTE2GOTOWHENEVER> ::= <DOSPTOS> <IDENTIFICADOR> <PARTE2GOTOWHENEVER> ::= <IDENTIFICADOR> <sENTENCIA4GL> ::= <SENTENCIAWHILE> <SENTENCIAWHILE> ::= while <EXPRBOOL> <SENTDELWHILE> end while <SENTDELWHILE> ::= <UNASENTDELWHILE> <MASSENTDELWHILE> <MASSENTDELWHILE> ::= <VACIO> <MASSENTDELWHILE> ::= <SENTDELWHILE> <UNASENTDELWHILE> ::= <SENTENCIA> <-----------> <INTEGEROVBLE> ::= <NÚMERO> <INTEGEROVBLE> ::= <VARIABLE> <STRINGSOVBLES> ::= <STRINGOVBLE> <MASSTRINGSOVBLES> <MASSTRINGSOVBLES> ::= <VACIO> <MASSTRINGSOVBLES> ::= <COMA> <STRINGSOVBLES> <OPCSTRINGOVBLE> ::= <VAIO> <OPCSTRINGOVBLE> ::= <STRINGOVBLE> <STRINGOVBLE> ::= <CTE_CAD> <STRINGOVBLE> ::= <VARIABLE> <PROPIETARIO> ::= <VACIO> <PROPIETARIO> ::= <CTE_CAD> <PTO> <PROPIETARIO> ::= <IDENTIFICADOR> <PTO> <NAMEDVALUE> ::= <VARIABLE> <NAMEDVALUE> ::= <CONSTANTE> <VARIABLE> ::= <VBLERECIBERDO> <CONSTANTE> ::= true <CONSTANTE> ::= false <CONSTANTE> ::= notfound <VARIABLES> ::= <VARIABLE> <MASVARIABLES> <MASVARIABLES> ::= <VACIO> <MASVARIABLES> ::= <COMA> <VARIABLES> <HELP> ::= <VACIO> <HELP> ::= help <NÚMERO> <OPCCHAR> ::= <VACIO> <OPCCHAR> ::= char <VBLESRECIBERDO> ::= <VBLERECIBERDO> <MASVBLESRECIBERDO> <MASVBLERECIBERDO> ::= <VACIO> <MASVBLERECIBERDO> ::= <COMA> <VBLESRECIBERDO> <VBLERECIBERDO> ::= <IDENTIFICADOR> <RESTOVBLERECIBERDO> <RESTOVBLERECIBERDO> ::= <VACIO> <RESTOVBLERECIBERDO> ::= <PTO> <VBLERECIBERDO> <RESTOVBLERECIBERDO> ::= <COR1> <DIMELTOARRAY> <COR2> <RETOARRAYRECIBERDO> <RETOARRAYRECIBERDO> ::= <VACIO> <RETOARRAYRECIBERDO> ::= <PTO> <IDENTIFICADOR> <RESTOARRAYRECIBERDO> <DIMELTOARRAY> ::= <EXPRINT> <RESTODIMELTOARRAY> maximo 3 dimensiones <RESTODIMELTOARRAY> ::= <VACIO> <RESTODIMELTOARRAY> ::= <COMA> <EXPRINT> <RESTODIMELTOARRAY> <LISTADEVBLES> ::= <LISTADEVBLE> <MASLISTADEVBLES> <MASLISTADEVBLES> ::= <VACIO>

Page 38: IfxToJava2

38

<MASLISTADEVBLES> ::= <COMA> <LISTADEVBLES> <LISTADEVBLE> ::= <IDENTIFICADOR> <RESTOLISTADEVBLE> <RESTOLISTADEVBLE> ::= <VACIO> <RESTOLISTADEVBLE> ::= <PTO> <RESTOREGLISTADEVBLE> <RESTOLISTADEVBLE> ::= <COR1> <DIMELTOARRAY> <COR2> <RESTOREGLISTADEVBLE> ::= <IDENTIFICADOR> <MASRESTOREGLISTADEVBLE> <RESTOREGLISTADEVBLE> ::= <ASTERISCO> <MASRESTOREGLISTADEVBLE> ::= <PTO> <RESTOREGLISTADEVBLE> <MASRESTOREGLISTADEVBLE> ::= <ULTIMOREGLISTADEVBLE> <ULTIMOREGLISTADEVBLE> ::= <VACIO> <ULTIMOREGLISTADEVBLE> ::= through <HASTAREGLISTADEVBLE> <ULTIMOREGLISTADEVBLE> ::= thru <HASTAREGLISTADEVBLE> <HASTAREGLISTADEVBLE> ::= <IDENTIFICADOR> <PTO> <IDENTIFICADOR> <MASHASTAREGLISTADEVBLE> <MASHASTAREGLISTADEVBLE> ::= <VACIO> <MASHASTAREGLISTADEVBLE> ::= <PTO> <IDENTIFICADOR> <MASHASTAREGLISTADEVBLE> <ARGUMENTOS> ::= <PAR1> <ARGS> <PAR2> <ARGS> ::= <VACIO> <ARGS> ::= <ARGUMENTO> <MASARGUMENTOS> <ARGUMENTO> ::= <IDENTIFICADOR> <MASARTUMENTOS> ::= <VACIO> <MASARGUMENTOS> ::= <COMA> <ARGUMENTO> <MASARGUMENTOS> <ARGUMENTOREPORT> ::= <IDENTIFICADOR> <RESTOARGREPORT> <RESTOARGREPORT> ::= <VACIO> <RESTOARGREPORT> ::= <PTO> <ARTUMENTOREPORT> <COLUMNLIST> ::= <IDENTIFICADOR> <RESTO1COLUMNLIST> <MASCOLUMNLIST> <MASCOLUMNLIST> ::= <VACIO> <MASCOLUMNLIST> ::= <COMA> <COLUMNLIST> <RESTO1COLUMNLIST> ::= <VACIO> <RESTO1COLUMNLIST> ::= <PTO> <RESTO2COLUMNLIST> <RESTO2COLUMNLIST> ::= <IDENTIFICADOR> <RESTO3COLUMNLIST> <RESTO2COLUMNLIST> ::= <ASTERISCO> <RESTO3COLUMNLIST> ::= <VACIO> <RESTO3COLUMNLIST> ::= <PTO> <IDENTIFICADOR> <CAMPOS> ::= <CAMPO> <MASCAMPOS> <MASCAMPOS> ::= <VACIO> <MASCAMPOS> ::= <COMA> <CAMPO> <MASCAMPOS> <CAMPO> ::= <IDENTIFICADOR> <CLAUSULASCAMPO> ::= <CLAUSULACAMPO> <MASCLAUSULACAMPO> <MASCLAUSULACAMPO> ::= <VACIO> <MASCLAUSULACAMPO> ::= <COMA> <CLAUSULACAMPO> <MASCLAUSULACAMPO> <CLAUSULACAMPO> ::= <IDENTIFICADOR> <PARTE1CLAUSULACAMPO> <CLAUSULACAMPO> ::= formonly <PTO> <PARTE2CLAUSULACAMPO> <PARTE1CLAUSULACAMPO> ::= <VACIO> <PARTE1CLAUSULACAMPO> ::= <COR1> <EXPRINT> <COR2> <PTO> <PARTE2CLAUSULACAMPO> <PARTE1CLAUSULACAMPO> ::= <PTO> <PARTE2CLAUSULACAMPO> <PARTE2CLAUSULACAMPO> ::= <IDENTIFICADOR> <PARTE2CLAUSULACAMPO> ::= <ASTERISCO> <PARTE2CLAUSULACAMPO> ::= <THRUNOTACION> <THRUNOTACION> ::= thru <IDENTIFICADOR> <RESTOTHRUNOTACION> <THRUNOTACION> ::= through <IDENTIFICADOR> <RESTOTHRUNOTACION> <RESTOTHRUNOTACION> ::= <COR1> <EXPRINT> <COR2> <PTO> <IDENTIFICADOR> <RESTOTHRUNOTACION> ::= <PTO> <IDENTIFICADOR> <ATTRIBUTECLAUSE> ::= <VACIO> <ATTRIBUTECLAUSE> ::= attribute <PAR1> <COLORATTRIBUTE> <MODATTRIBUTE> <PAR2> <COLORATTRIBUTE> ::= <UNMODATTRIBUTE> <COLORATTRIBUTE> ::= black

Page 39: IfxToJava2

39

<COLORATTRIBUTE> ::= blue <COLORATTRIBUTE> ::= cyan <COLORATTRIBUTE> ::= green <COLORATTRIBUTE> ::= magenta <COLORATTRIBUTE> ::= red <COLORATTRIBUTE> ::= white <COLORATTRIBUTE> ::= yellow <COLORATTRIBUTE> ::= bold <COLORATTRIBUTE> ::= dim <COLORATTRIBUTE> ::= invisible <COLORATTRIBUTE> ::= normal <MODATTRIBUTE> ::= <COMA> <UNMODATTRIBUTE> <MODATTRIBUTE> <MODATTRIBUTE> ::= <VACIO> <UNMODATTRIBUTE> ::= reverse <UNMODATTRIBUTE> ::= blink <UNMODATTRIBUTE> ::= underline <OPENWINDOWATTRIBUTECLAUSE> ::= <VACIO> <OPENWINDOWATTRIBUTECLAUSE> ::= attribute <PAR1> <OWCOLORATTRIBUTE> <OWMASMODATTRIBUTE> <PAR2> <OWCOLORATTRIBUTE> ::= <OWUNMODATTRIBUTE> <OWCOLORATTRIBUTE> ::= black <OWCOLORATTRIBUTE> ::= blue <OWCOLORATTRIBUTE> ::= cyan <OWCOLORATTRIBUTE> ::= green <OWCOLORATTRIBUTE> ::= magenta <OWCOLORATTRIBUTE> ::= red <OWCOLORATTRIBUTE> ::= white <OWCOLORATTRIBUTE> ::= yellow <OWCOLORATTRIBUTE> ::= bold <OWCOLORATTRIBUTE> ::= dim <OWCOLORATTRIBUTE> ::= normal <OWUNMODATTRIBUTE> ::= reverse <OWUNMODATTRIBUTE> ::= border <OWUNMODATTRIBUTE> ::= <OTROOWMODATTTRIBUTE> line <RESERVEDLINEPOSITION> <OTROOWMODATTTRIBUTE> ::= comment <OTROOWMODATTTRIBUTE> ::= form <OTROOWMODATTTRIBUTE> ::= menu <OTROOWMODATTTRIBUTE> ::= message <OTROOWMODATTTRIBUTE> ::= prompt <RESERVEDLINEPOSITION> ::= first <FIRSTRESERVEDLINEPOSITION> <RESERVEDLINEPOSITION> ::= last <LASTRESERVEDLINEPOSITION> <RESERVEDLINEPOSITION> ::= <INTEGEROVBLE> <FIRSTRESERVEDLINEPOSITION> ::= <MAS> <INTEGEROVBLE> <LASTRESERVEDLINEPOSITION> ::= <MENOS> <INTEGEROVBLE> <OWMASMODATTRIBUTE> ::= <COMA> <UNMODATTRIBUTE> <OWMASMODATTRIBUTE> <OWMASMODATTRIBUTE> ::= <VACIO> <OPTIONSATTRIBUTECLAUSE> ::= attribute <PAR1> <OPUNAUOTRA> <PAR2> <OPUNAUOTRA> ::= <OPCOLORATTRIBUTE> <OPMODATTRIBUTE> <OPUNAUOTRA> ::= form <OPUNAUOTRA> ::= window <OPCOLORATTRIBUTE> ::= <OPUNMODATTRIBUTE> <OPCOLORATTRIBUTE> ::= black <OPCOLORATTRIBUTE> ::= blue <OPCOLORATTRIBUTE> ::= cyan <OPCOLORATTRIBUTE> ::= green <OPCOLORATTRIBUTE> ::= magenta <OPCOLORATTRIBUTE> ::= red <OPCOLORATTRIBUTE> ::= white <OPCOLORATTRIBUTE> ::= yellow <OPCOLORATTRIBUTE> ::= bold <OPCOLORATTRIBUTE> ::= dim <OPCOLORATTRIBUTE> ::= normal

Page 40: IfxToJava2

40

<OPCOLORATTRIBUTE> ::= invisible <OPMODATTRIBUTE> ::= <COMA> <OPUNMODDATTRIBUTE> <OPMODATTRIBUTE> <OPMODATTRIBUTE> ::= <VACIO> <OPUNMODATTRIBUTE> ::= reverse <OPUNMODATTRIBUTE> ::= border <OPUNMODATTRIBUTE> ::= underline <RESERVEDLINEPOSITION> ::= first <FIRSTRESERVEDLINEPOSITION> <RESERVEDLINEPOSITION> ::= last <LASTRESERVEDLINEPOSITION> <RESERVEDLINEPOSITION> ::= <INTEGEROVBLE> <FIRSTRESERVEDLINEPOSITION> ::= <MAS> <INTEGEROVBLE> <FIRSTRESERVEDLINEPOSITION> ::= <VACIO> <LASTRESERVEDLINEPOSITION> ::= <MENOS> <INTEGEROVBLE> <LASTRESERVEDLINEPOSITION> ::= <VACIO> <PARAMETROSONKEY> ::= <PAR1> <KEYPARAM> <MASKEYPARAM> <PAR2> <MASKEYPARAM> ::= <VACIO> <MASKEYPARAM> ::= <COMA> <KEYPARAM> <MASKEYPARAM> <KEYPARAM> ::= <PALRES> <KEYPARAM> ::= <TECLAFUNCION> <KEYPARAM> ::= <CONTROLKEY> <CONTROLKEY> ::= control <GUION> <LETRA> <----------------> <EXPR4GL> ::= <EXPR> <EXPR> ::= <EXPRUSING> <MASEXPRUSING> <MASEXPRUSING> ::= <VACIO> <MASEXPRUSING> ::= using <EXPRUSING> <MASEXPRUSING> <EXPRUSING> ::= <EXPRCONDICIONALOR> <MASEXPRCONDICIONALOR> <MASEXPRCONDICIONALOR> ::= <VACIO> <MASEXPRCONDICIONALOR> ::= or <EXPRCONDICIONALOR> <MASEXPRCONDICIONALOR> <EXPRCONDICIONALOR> ::= <EXPRCONDICIONALAND> <MASEXPRCONDICIONALAND> <MASEXPRCONDICIONALAND> ::= <VACIO> <MASEXPRCONDICIONALAND> ::= and <EXPRCONDICIONALAND> <MASEXPRCONDICIONALAND> <EXPRCONDICIONALAND> ::= <EXPRIS> <MASEXPRIS> <MASEXPRIS> ::= <VACIO> <MASEXPRIS> ::= is null <MASESPRIS> null == <expris> <MASEXPRIS> ::= is not null <MASESPRIS> null == <expris> --> <exprprim> <cte> <EXPRIS> ::= <EXPRBETWEEN> <MASEXPRBETWEEN> <MASEXPRBETWEEN> ::= <VACIO> <MASEXPRBETWEEN> ::= between <EXPRBETWEEN> <MASEXPRBETWEEN> <EXPRBETWEEN> ::= <EXPRIN> <MASEXPRIN> <MASEXPRIN> ::= <VACIO> <MASEXPRIN> ::= in <PAR1> <EXPRS> <PAR2> <MASEXPRIN> MIRAR <EXPRIN> ::= <EXPRRELACION> <MASEXPRRELACION> <MASEXPRRELACION> ::= <VACIO> <MASEXPRRELACION> ::= compigual <EXPRRELACION> <MASEXPRRELACIOM> <MASEXPRRELACION> ::= compdesigual <EXPRRELACION> <MASEXPRRELACION> <MASEXPRRELACION> ::= menor <EXPRRELACION> <MASEXPRRELACION> <MASEXPRRELACION> ::= mayor <EXPRRELACION> <MASEXPRRELACION> <MASEXPRRELACION> ::= menorigual <EXPRRELACION> <MASEXPRRELACION> <MASEXPRRELACION> ::= mayorigual <EXPRRELACION> <MASEXPRRELACION> <EXPRRELACION> ::= <EXPRLIKE> <MASEXPRLIKE> <MASEXPRLIKE> ::= <VACIO> <MASEXPRLIKE> ::= like <EXPRLIKE> <MASEXPRLIKE> <MASEXPRLIKE> ::= matches <EXPRLIKE> <MASEXPRLIKE> <EXPRLIKE> ::= <EXPRCONCATENACION> <MASEXPRCONCATENACION> <MASEXPRCONCATENACION> ::= <VACIO> <MASEXPRCONCATENACION> ::= <CONCAT> <EXPRCONCATENACION> <MASEXPRCONCATENACION> <MASEXPRCONCATENACION> ::= <COMA> <EXPRCONCATENACION> <MASEXPRCONCATENACION> <EXPRCONCATENACION> ::= <EXPRADICION> <MASEXPRADICION>

Page 41: IfxToJava2

41

<MASEXPRADICION> ::= <VACIO> <MASEXPRADICION> ::= mas <EXPRADICION> <MASEXPRADICION> <MASEXPRADICION> ::= menos <EXPRADICION> <MASEXPRADICION> <EXPRADICION> ::= <EXPRMULTIPLY> <MASEXPRMULTIPLY> <MASEXPRMULTIPLY> ::= <VACIO> <MASEXPRMULTIPLY> ::= <POR> <EXPRMULTIPLY> <MASEXPRMULTIPLY> <MASEXPRMULTIPLY> ::= <ENTRE> <EXPRMULTIPLY> <MASEXPRMULTIPLY> <EXPRMULTIPLY> ::= <EXPREXPMOD> <MASEXPREXPMOD> <MASEXPREXPMOD> ::= <MOD> <EXPREXPMOD> <MASEXPREXPMOD> <MASEXPREXPMOD> ::= <EXP> <EXPREXPMOD> <MASEXPREXPMOD> <EXPREXPMOD> ::= <EXPRUNITS> <MASEXPRUNITS> <MASEXPRUNITS> ::= <VACIO> <MASEXPRUNITS> ::= units <CTEUNITS> <MASEXPRUNITS> <EXPRUNITS> ::= <EXPRUNARIA> <EXPRUNARIA> ::= ascii <EXPRUNARIA> <EXPRUNARIA> ::= <EXPRUNARIA> clipped <EXPRUNARIA> ::= column <EXPRUNARIA> <EXPRUNARIA> ::= ord <PAR1> <EXPRUNARIA> <PAR2> <EXPRUNARIA> ::= <EXPRUNARIA> spaces <EXPRUNARIA> ::= <EXPRUNARIA> wordwrap <EXPRUNARIA> ::= not <EXPRUNARIA> <EXPRUNARIA> ::= <MAS> <EXPRUNARIA> <EXPRUNARIA> ::= <MENOS> <EXPRUNARIA> <EXPRUNARIA> ::= <EXPRUNARIA> units <EXPRUNITS> <EXPRUNARIA> ::= <EXPRPRIMARIA> <EXPRPRIMARIA> ::= <PARENTESIS1> <EXPR> <PARENTESIS2> <EXPRPRIMARIA> ::= <LITERAL> <EXPRPRIMARIA> ::= <VARIABLE> <EXPRPRIMARIA> ::= <LLAMADAFUNCION> <EXPRPRIMARIA> ::= <LLAMADAFUNCIONPREDEFINIDA> <EXPRPRIMARIA> ::= <EXPRESIONAGREGADA> <LITERAL> ::= ctecualquiertipo <CTEUNITS> ::= year <CTEUNITS> ::= month <CTEUNITS> ::= day <CTEUNITS> ::= hour <CTEUNITS> ::= minute <CTEUNITS> ::= second <CTEUNITS> ::= fraction <LLAMADAFUNCION> ::= <IDENTIFICADOR> <PAR1> <ARGSLLAMADAF> <PAR2> <RESTOSENTENCIACALL> <ARGSLLAMADAF> ::= <VACIO> <ARGSLLAMADAF> ::= <EXPR4GL> <MASARGSLLAMADAF> <MASARGSLLAMADAF> ::= <VACIO> <MASARGSLLAMADAF> ::= <COMA> <EXPR4GL> <MASARGSLLAMADAF> <LLAMADAFUNCIONPREDEFINIDA> ::= <AGREGATEREPORTFUNCTIONS> <LLAMADAFUNCIONPREDEFINIDA> ::= <AGREGATEFUNCTIONS> <AGRETATEREPORTFUNCTIONS> ::= <OPCGROUPAGREGATE> <UNAAGREGATEREPORFUNCTION> <OPCGROUPAGREGATE> ::= <VACIO> <OPCGROUPAGREGATE> ::= group <UNAAGRETATEREPORTFUNCTION> ::= <VACIO> <UNAAGRETATEREPORTFUNCTION> ::= percent <RESTOPERCENTCONUNT> <UNAAGRETATEREPORTFUNCTION> ::= count <RESTOPERCENTCONUNT> <UNAAGRETATEREPORTFUNCTION> ::= avg <RESTOAVGSUM> <OPCAVGSUMMAXMIN> <UNAAGRETATEREPORTFUNCTION> ::= sum <RESTOAVGSUM> <OPCAVGSUMMAXMIN> <UNAAGRETATEREPORTFUNCTION> ::= max <EXPR4GL> <OPCAVGSUMMAXMIN> <UNAAGRETATEREPORTFUNCTION> ::= min <EXPR4GL> <OPCAVGSUMMAXMIN> <RESTOPERCENTCONUNT> ::= <PAR1> <ASTERISCO> <PAR2> <RESTOAVGSUM> ::= <EXPRNUM> <RESTOAVGSUM> ::= <INBERVALVALUE>

Page 42: IfxToJava2

42

<OPCAVGSUMMAXMIN> ::= <VACIO> <OPCAVGSUMMAXMIN> ::= where <EXPRBOOL> <AGREGATEFUNCTIONS> ::= arg_val <PAR1> <EXPR> <PAR2> <AGREGATEFUNCTIONS> ::= arr_count <PAR1> <PAR2> <AGREGATEFUNCTIONS> ::= arg_curr <PAR1> <PAR2> <AGREGATEFUNCTIONS> ::= cursor_name <PAR1> <EXPR> <PAR2> <AGREGATEFUNCTIONS> ::= downshift <PAR1> <EXPR> <PAR2> <AGREGATEFUNCTIONS> ::= upshift <PAR1> <EXPR> <PAR2> <AGREGATEFUNCTIONS> ::= err_get <PAR1> <EXPR> <PAR2> <AGREGATEFUNCTIONS> ::= fgl_drawbox <PAR1> <EXPR> <PAR2> <AGREGATEFUNCTIONS> ::= fgl_getenv <PAR1> <EXPR> <PAR2> <AGREGATEFUNCTIONS> ::= fgl_getkey <PAR1> <PAR2> <AGREGATEFUNCTIONS> ::= fgl_keyval <PAR1> <EXPR> <PAR2> <AGREGATEFUNCTIONS> ::= fgl_lastkey <PAR1> <PAR2> <AGREGATEFUNCTIONS> ::= fgl_scr_size <PAR1> <EXPR> <PAR2> <AGREGATEFUNCTIONS> ::= length <PAR1> <EXPR> <PAR2> <AGREGATEFUNCTIONS> ::= nuv_args <PAR1> <PAR2> <AGREGATEFUNCTIONS> ::= ord <PAR1> <EXPR> <PAR2> <AGREGATEFUNCTIONS> ::= scr_line <PAR1> <PAR2> <AGREGATEFUNCTIONS> ::= set_count <PAR1> <PAR2> <EXPRAGREGADA> ::= current <RESTOCURRENT> <EXPRAGREGADA> ::= date <RESTODATE> <EXPRAGREGADA> ::= day <PAR1> <EXPR> <PAR2> <EXPRAGREGADA> ::= month <PAR1> <EXPR> <PAR2> <EXPRAGREGADA> ::= year <PAR1> <EXPR> <PAR2> <EXPRAGREGADA> ::= weekday <PAR1> <EXPR> <PAR2> <EXPRAGREGADA> ::= extend <PAR1> <EXPR> <OPCDATETIMEQUALIFIER> <PAR2> <EXPRAGREGADA> ::= field_touched <PAR1> <SUBCLAUSULASCAMPO> <PAR2> <EXPRAGREGADA> ::= get_fldbuf <PAR1> <SUBCLAUSULACAMPO> <PAR2> <EXPRAGREGADA> ::= infield <PAR1> <SUBCLAUSULACAMPO> <PAR2> <EXPRAGREGADA> ::= pageno <EXPRAGREGADA> ::= lineno <EXPRAGREGADA> ::= today <EXPRAGREGADA> ::= time <RESTOTIME> <RESTOCURRENT> ::= <VACIO> <RESTOCURRENT> ::= <DATETIMEQUALIFIER> <RESTODATE> ::= <VACIO> <RESTODATE> ::= <PAR1> <EXPR> <PAR2> <RESTOTIME> ::= <VACIO> <RESTOTIME> ::= <PAR1> <EXPR> <PAR2> <------------> <SENTENCIASQL> ::= <SENTENCIAALTER> <SENTENCIAALTER> ::= alter <RESTOSENTENCIAALTER> <RESTOSENTENCIAALTER> ::= <SENTENCIAALTERINDEX> <RESTOSENTENCIAALTER> ::= <SENTENCIAALTERTABLE> <SENTENCIAALTERINDEX> ::= index <ELTONAME> to <OPCNOT> cluster <SENTENCIAALTERTABLE> ::= table <ELTONAME> <ALTERTABLECLAUSULAS> <ALTERTABLECLAUSULAS> ::= <UNAALTERTABLECLAUSULAS> <MASALTERTABLECLAUSULAS> <MASALTERTABLECLAUSULAS> ::= <VACIO> <MASALTERTABLECLAUSULAS> ::= <COMA> <UNAALTERTABLECLAUSULAS> <MASALTERTABLECLAU <UNAALTERTABLECLAUSULAS> ::= add <RESTOADDALTERCLAUSULA> <UNAALTERTABLECLAUSULAS> ::= drop <RESTODROPALTERCLAUSULA> <UNAALTERTABLECLAUSULAS> ::= modify <RESTOMODIFYALTERCLAUSULA> <UNAALTERTABLECLAUSULAS> ::= lock mode <PAR1> <PAGEOROW> <PAR2> <RESTOADDALTERCLAUSULA> ::= constraint <TABLACONSTRAINTDEF> <RESTOADDALTERCLAUSULA> ::= <PAR1> <ADDCOLUMNSDEFINITION> <PAR2> <ADDCOLUMNSDEFINITION>::= <UNAADDCOLUMNSDEFINITION> <MASADDCOLUMNSDEFINITION>

Page 43: IfxToJava2

43

<MASADDCOLUMNSDEFINITION> ::= <VACIO> <MASADDCOLUMNSDEFINITION> ::= <UNAADDCOLUMNSDEFINITION> <MASADDCOLUMNSDEFINITIO <UNAADDCOLUMNSDEFINITION> ::= <COLUMNDEFINITION> <OPCBEFORECOLUMN> <OPCBEFORECOLUMN> ::= <VACIO> <OPCBEFORECOLUMN> ::= before <IDENTIFICADOR> <RESTOMODIFYALTERCLAUSULA> ::= next size <ENTERO> <RESTOMODIFYALTERCLAUSULA> ::= <PAR1> <COLUMNSDEFINITION> <PAR2> <RESTODROPALTERCLAUSULA> ::= constraint <PAR1> <ELTOSNAME> <PAR2> <RESTODROPALTERCLAUSULA> ::= <PAR1> <COLUMNS> <PAR2> <COLUMNDEFINITION> ::= <UNACOLUMNDEFINITION> <MASCOLUMNDEFINITION> <MASCOLUMNDEFINITION> ::= <COMA> <UNACOLUMNDEFINITION> <MASCOLUMNDEFINITION> <MASCOLUMNDEFINITION> ::= <VACIO> <SENTENCIASQL> ::= <SENTENCIABEGINWORK> <SENTENCIABEGINWORK> ::= begin work <SENTENCIASQL> ::= <SENTENCIACLOSE> <SENTENCIACLOSE> ::= <SENTENCIACLOSECURSOR> <SENTENCIACLOSE> ::= <SENTENCIACLOSEDATABASE> <SENTENCIACLOSECURSOR> ::= close <IDENTIFICADOR> <SENTENCIACLOSEDATABASE> ::= close database <SENTENCIASQL> ::= <SENTENCIACOMMITWORK> <SENTENCIACOMMITWORK> ::= commit work <SENTENCIASQL> ::= <SENTENCIACONNECT> <SENTENCIACONNECT> ::= connect to <NOMBREBD> <SENTENCIASQL> ::= <SENTENCIACREATE> <SENTENCIACREATE> ::= create <RESTOSENTENCIACREATE> <RESTOSENTENCIACREATE> ::= audit for <ELTONAME> in <CTE_CAD> <RESTOSENTENCIACREATE> ::= database <SENTENCIACREATEDATABASE> <RESTOSENTENCIACREATE> ::= procedure from <STRINGOVBLE> <RESTOSENTENCIACREATE> ::= table <SENTENCIACREATETABLE> <RESTOSENTENCIACREATE> ::= temp table <SENTENCIACREATETEMPTABLE> <RESTOSENTENCIACREATE> ::= view <SENTENCIACREATEVIEW> <RESTOSENTENCIACREATE> ::= <OPCUNIQUEDISTINCT> <OPCCLUSTER> index <SENTENCIACREATEINDEX> <RESTOSENTENCIACREATE> ::= <OPCPUBLICPRIVATE> synonym <SENTENCIACREATESYNONYM> <SENTENCIACREATEDATABASE> ::= <NOMBREDB> <OPCSELOG> <OPCSELOG> ::= <VACIO> <OPCSELOG> ::= with log in <CTE_CAD> <OPCMODEANSI> <OPCMODEANSI> ::= <VACIO> <OPCMODEANSI> ::= mode ansi <SENTENCIACREATEINDEX> ::= <ELTONAME> on <ELTONAME> <PAR1> <ELTOSINDICE> <PAR2> <ELTOSINDICE> ::= <ELTOINDICE> <MASELTOSINDICE> <MASELTOSINDICE> ::= <VACIO> <MASELTOSINDICE> ::= <COMA> <ELTOINDICE> <MASELTOSINDICE> <ELTOINDICE> ::= <IDENTIFICADOR> <OPCASCDESC> <SENTENCIACREATESYNONYM> ::= <ELTONAME> for <ELTONAME> <SENTENCIACREATETABLE> ::= <ELTONAME> <PAR1> <CAMPOSCREATETABLE> <PAR2> <OPCSTORAGEOPTION> <OPCSTORAGEOPTION> ::= <VACIO> <OPCSTORAGEOPTION> ::= in <CTE_CAD> <OPCSTORAGEOPTION> ::= in <VARIABLE> <OPCEXTENTOPC> <OPCLOCKMODE> <OPCEXTENTOPC> ::= <VAIO>

Page 44: IfxToJava2

44

<OPCEXTENTOPC> ::= <OPCEXTENTSIZE> <OPCNEXTSIZE> <OPCEXTENTOPC> ::= <OPCNEXTSIZE> <OPCEXTNTSIZE> ::= <VACIO> <OPCEXTNTSIZE> ::= extent size <ENTERO> <OPCNEXTSIZE> ::= <VACIO> <OPCNEXTSIZE> ::= next size <ENTERO> <OPCLOCKMODE> ::= <VACIO> <OPCLOCKMODE> ::= lock mode <OPCPAGEROW> <CAMPOSCREATETABLE> ::= <COLUMNDEFINITION> <RESTOCAMPOSCREATETABLE> <COLUMNDEFINITION> ::= <IDENTIFICADOR> <TIPODATOSQL> <OPCNOTNULL> <OPCCOLUMNCONSTRAINTDEF> <OPCCOLUMNCONSTRAINTDEF> ::= <UNIQUEDISTINCT> <OPCCONSTRAINT> <RESTOCAMPOSCREATETABLE> ::= <VACIO> <RESTOCAMPOSCREATETABLE> ::= <COMA> <CONSTRAINTDEF> <RESTOCAMPOSCREATETABLE> <CONSTRAINTDEF> ::= <UNIQUEDISTINCT> <PAR1> <COLUMNS> <PAR2> <OPCCONSTRATINT> <SENTENCIACREATETEMPTABLE> ::= <IDENTIFICADOR> <PAR1> <CAMPOSCREATETEMPTABLE> <PAR2> <OPCWHITNOLOG> <OPCSTORAGEOPTION> <OPCWITHNOLOG> ::= <VACIO> <OPCWITHNOLOG> ::= with no log <CAMPOSCREATETEMPTABLE> ::= <TEMPCOLUMNSDEFINITION> <RESTOCAMPOSCREATETEMPTABLE> <TEMPCOLUMNSDEFINITION> ::= <UNATEMPCOLUMNDEFINITION> <MASTEMPCOLUMNDEFINITION> <MASTEMPCOLUMNDEFINITION> ::= <VACIO> <MASTEMPCOLUMNDEFINITION> ::= <COMA> <UNATEMPCOLUMNDEFINITION> <MASTEMPCOLUMNDEFINITION> <UNATEMPCOLUMNDEFINITION> ::= <IDENTIFICADOR> <TIPODATOSQL> <OPCNOTNULL> <OPCTEMPCOLUMNCONSTRAINTDEF> <OPCTEMPCOLUMNCONSTRAINTDEF> ::= unique <OPCTEMPCOLUMNCONSTRAINTDEF> ::= distinct <OPCTEMPCOLUMNCONSTRAINTDEF> ::= primary key <OPCTEMPCOLUMNCONSTRAINTDEF> ::= <CHECKCLAUSE> <CHECKCLAUSE> ::= check <PAR1> <EXPRSQL> <PAR2> <RESTOCAMPOSCREATETEMPTABLE> ::= <VACIO> <RESTOCAMPOSCREATETEMPTABLE> ::= <COMA> <TEMPCONSTRAINTDEF> <RESTOCAMPOSCREATETEMPTABLE> <TEMPCONSTRAINTDEF> ::= <CHECKCLAUSE> <TEMPCONSTRAINTDEF> ::= <UNATEMPCONSTRAINTDEF> <OTRATEMPCONSTRAINTDEF> <UNATEMPCONSTRAINTDEF> ::= unique <UNATEMPCONSTRAINTDEF> ::= distinct <UNATEMPCONSTRAINTDEF> ::= primary key <OTRATEMPCONSTRAINTDEF> ::= <PAR1> <COLUMNS> <PAR2> <SENTENCIACREATEVIEW> ::= <ELTONAME> <OPCCOLUMNS> as <SENTENCIASELECT> <OPCWITHCHECKOPTION> <OPCWITHCHECKOPTION> ::= <VACIO> <OPCWITHCHECKOPTION> ::= with check option <SENTENCIASQL> ::= <SENTENCIADATABASE> <SENTENCIADATABASE> ::= <VACIO> <SENTENCIADATABASE> ::= database <NOMBREDB> <ATRIBDB> <ATRIBDB> ::= <VACIO> <ATRIBDB> ::= exclusive <NOMBREDB> ::= <VARIABLE> <NOMBREDB> ::= <CTE_CADENA> <SENTENCIASQL> ::= <SENTENCIADECLARE> <SETENCIADECLARE> ::= declare <IDENTIFICADOR> <CURSOROSCROLLCURSOR> <CURSOROSCROLLCURSOR> ::= cursor <OPCWITHHOLD> for <SENTDELCURSOR> <CURSOROSCROLLCURSOR> ::= scroll cursor <OPCWITHHOLD> for <SENTDELSCROLLCURSOR> <SENTDELCURSOR> ::= <SENTENCIAINSERT>

Page 45: IfxToJava2

45

<SENTDELCURSOR> ::= <SENTENCIASELECT> <OPCFORUPDATECURSOR> <OPDFORUPDATECURSOR> ::= <VACIO> <OPCFORUPDATECURSOR> ::= for update <MASFORUPDATECURSOR> <MASFORUPDATECURSOR> ::= <VACIO> <MASFORUPDATECURSOR> ::= of <COLUMNS> <SENTDELCURSOR> ::= <IDENTIFICADOR> <SENTDELSCROLLCURSOR> ::= <SENTENCIASELECT> <SENTDELSCROLLCURSOR> ::= <IDENTIFICADOR> <SENTENCIASQL> ::= <SENTENCIADELETE> <SENTENCIADELETE> ::= delete from <ELTONAME> <OPCRESTODELETE> <OPCRESTODELETE> ::= <VACIO> <OPCRESTODELETE> ::= where <MASRESTODELETE> <MASRESTODELETE> ::= current of <IDENTIFICADOR> <MASRESTODELETE> ::= <EXPRSQL> <SENTENCIASQL> ::= <SENTENCIADISCONNECT> <SENTENCIADISCONNECT> ::= disconnect current <SENTENCIASQL> ::= <SENTENCIADROP> <SENTENCIADROP> ::= drop <RESTOSENTDROP> <RESTOSENTDROP> ::= audit for <ELTONAME> <RESTOSENTDROP> ::= database <NOMBREDB> <RESTOSENTDROP> ::= index <ELTONAME> <RESTOSENTDROP> ::= synonym <ELTONAME> <RESTOSENTDROP> ::= table <ELTONAME> <RESTOSENTDROP> ::= view <ELTONAME> <SENTENCIASQL> ::= <SENTENCIAEXECUTE> <SENTENCIAEXECUTE> ::= execute <RESTOSENTEXECUTE> <RESTOSENTEXECUTE> ::= <IDENTIFICADOR> <RESTOSENTENCIAEXECUTE> <RESTOSENTENCIAEXECUTE> ::= <VACIO> <RESTOSENTENCIAEXECUTE> ::= <USINGOINTO> <LISTADEVBLES> <RESTOSENTEXECUTE> ::= immediate <STRINGOVBLE> <SENTENCIASQL> ::= <SENTENCIAFETCH> <SETENCIAFETCH> ::= fetch <PARTE1FETCH> <IDENTIFICADOR> <OPCPARTE2FETCH> <PARTE1FETCH> ::= <VACIO> <PARTE1FETCH> ::= next <PARTE1FETCH> ::= previous <PARTE1FETCH> ::= prior <PARTE1FETCH> ::= first <PARTE1FETCH> ::= last <PARTE1FETCH> ::= current <PARTE1FETCH> ::= relative <OPCMASMENOS> <INTEGEROOVBE> <PARTE1FETCH> ::= absolute <INTEGEROVBLE> <OPCPARTE2FETCH> ::= <VACIO> <OPCPARTE2FETCH> ::= into <LISTADEVBLES> <SENTENCIASQL> ::= <SENTENCIAFLUSH> <SENTENCIAFLUSH> ::= flush <IDENTIFICADOR> <SENTENCIASQL> ::= <SENTENCIAFREE> <SENTENCIAFREE> ::= free <IDENTIFICADOR> <SENTENCIAFREE> ::= free <VARIABLE> <SENTENCIASQL> ::= <SENTENCIAGRANT> <SENTENCIAGRANT> ::= grant <RESTOSENTGRANT> <RESTOSENTGRANT> ::= <DATABASEPRIVILEGES> to <USERSGRANT> <RESTOSENTGRANT> ::= <TABLEPRIVILEGES> on <ELTONAME> to <USERGRANT> <OPCGRANTOPT> <OPCASVALOR> <USERSGRANT> ::= public <USERSGRANT> ::= <USUARIOS> <DATABASEPRIVILEGES> ::= connect

Page 46: IfxToJava2

46

<DATABASEPRIVILEGES> ::= resource <DATABASEPRIVILEGES> ::= dba <TABLEPRIVILEGES> ::= all <OPCPRIVILEGES> <TABLEPRIVILEGES> ::= <UNPRIVILEGE> <MASPRIVILEGES> <MASPRIVILEGES> ::= <VACIO> <MASPRIVILEGES> ::= <COMA> <UNPRIVILEGE> <MASPRIVILEGES> <UNPRIVILEGES> ::= insert <UNPRIVILEGES> ::= delete <UNPRIVILEGES> ::= index <UNPRIVILEGES> ::= alter <UNPRIVILEGES> ::= update <OPCRESTOTABLEPRIVILEGES> <UNPRIVILEGES> ::= select <OPCRESTOTABLEPRIVILEGES> <OPCRESTOTABLEPRIVILEGES> ::= <PAR1> <COLUMNS> <PAR2> <SENTENCIASQL> ::= <SENTENCIAINSERT> <SENTENCIAINSERT> ::= insert into <ELTONAME> <OPCCOLUMNS> <RESTOSENTINSERT> <RESTOINSERT> ::= <SENTENCIASELECT> <RESTOINSERT> ::= <CLAUSULAVALUES> <SENTENCIASQL> ::= <SENTENCIALOAD> <SENTENCIALOAD> ::= load from <STRINGOVBLE> <OPCDELIMITER> <RESTOSENTLOAD> <RESTOSENTLOAD> ::= insert into <EXPRNAME> <OPCCOLUMNS> <RESTOSENTLOAD> ::= <VARIABLE> <SENTENCIASQL> ::= <SENTENCIALOCK> <SENTENCIALOCK> ::= lock table <ELTONAME> in <SHAREEXCLUSIVE> mode <SENTENCIASQL> ::= <SENTENCIAOPEN> <SENTENCIAOPEN> ::= open <IDENTIFICADOR> <RESTOSENTOPEN> <RESTOSENTOPEN> ::= <VACIO> <RESTOSENTOPEN> ::= using <VARIABLES> <OPCWITHREOPTIMIZATION> <SENTENCIASQL> ::= <SENTENCIAPREPARE> <SENTENCIAPREPARE> ::= prepare <IDENTIFICADOR> from <STRINGOVBLE> <SENTENCIASQL> ::= <SENTENCIAPUT> <SENTENCIAPUT> ::= put <IDENTIFICADOR> <RESTOSENTPUT> <RESTOSENTPUT> ::= <VACIO> <RESTOSENTPUT> ::= from <VARIABLES> <SENTENCIASQL> ::= <SENTENCIARECOVER> <SENTENCIARECOVER> ::= recover table <ELTONAME> <SENTENCIASQL> ::= <SENTENCIARENAME> <SENTENCIARENAME> ::= rename <RESTOSENTRENAME> <RESTOSENTRENAME> ::= column <ELTONAME> <PTO> <IDENTIFICADOR> to <IDENTIFICADOR> <RESTOSENTRENAME> ::= table <OPCIDPTO> <IDENTIFICADOR> to <IDENTIFICADOR> <SENTENCIASQL> ::= <SENTENCIAREVOKE> <SENTENCIAREVOKE> ::= revoke <PARTE1SENTREVOKE> <PARTE2SENTREVOKE> <PARTE1SENTREVOKE> ::= <TABLEPRIVILEGES> on <ELTONAME> <PARTE1SENTREVOKE> ::= <DATABASEPRIVILEGES> <PARTE2SENTREVOKE> ::= from <MASPARTE2SENTREVOKE> <MASPARTE2SENTREVOKE> ::= public <MASPARTE2SENTREVOKE> ::= <COLUMNS> <TABLEPRIVILEGES> ::= all <OPCPRIVILEGES> <TABLEPRIVILEGES> ::= <UNPRIVILEGIO> <MASPRIVILEGIOS> <MASPRIVILEGIOS> ::= <VACIO> <MASPRIVILEGIOS>::= <COMA> <UNPRIVILEGIO> <MASPRIVILEGIOS> <UNPRIVILEGIO> ::= insert <UNPRIVILEGIO> ::= delete <UNPRIVILEGIO> ::= select <UNPRIVILEGIO> ::= update

Page 47: IfxToJava2

47

<UNPRIVILEGIO> ::= index <UNPRIVILEGIO> ::= alter <DATABASEPRIVILEGES> ::= connect <DATABASEPRIVILEGES> ::= dba <DATABASEPRIVILEGES> ::= resource <SENTENCIASQL> ::= <SENTENCIAROLLBACK> <SENTENCIAROLLBACK> ::= rollback work <SENTENCIASQL> ::= <SENTENCIAROLLFORWARD> <SENTENCIAROLLFORWARD> ::= rollforward database <NOMBREDB> <SENTENCIASQL> ::= <SENTENCIASELECT> <SENTENCIASELECT> ::= select <SELECTCLAUSE> <OPCINTOCLAUSE> <FROMCLAUSE> <RESTO1SENTSELECT> <RESTO1SENTSELECT> ::= <UNIONSELECT> <RESTO1SENTSELECT> ::= <OPCWHERECLAUSE> <OPCGROUPBYCLAUSE> <OPCHAVINGCLAUSE> <RESTO2SENTSELECT> <RESTO2SENTSELECT> ::= <UNIONSELECT> <RESTO2SENTSELECT> ::= <OPCORDERBYCLAUSE> <OPCINTOTEMPCLAUSE> <UNIONSELECT> ::= union <OPCALL> <SENTENCIASELECT> <SELECTCLAUSE> ::= <OPCALLUNIQUEDISTINCT> <RESTOSELECTCLAUSE> <RESTOSELECTCLAUSE> ::= <UNASELECTITEM> <MASSELECTITEM> <MASSELECTITEM> ::= <VACIO> <MASSELECTITEM> ::= <COMA> <UNASELECTITEM> <MASSELECTITEM> <UNASELECTITEM> ::= <ASTERISCO> <UNASELECTITEM> ::= <PROPIETARIOSQL> <IDENTIFICADOR> <PTO> <ASTERISCO> <UNASELECTITEM> ::= <EXPRSQL> <RESTOUNASELECTITEM> <RESTOUNASELECTITEM> ::= <VACIO> <RESTOUNASELECTITEM> ::= <OPCAS> <IDENTIFICADOR> <OPCINTOCLAUSE> ::= <VACIO> <OPCINTOCLAUSE> ::= into <LISTADEVBLES> <FROMCLAUSE> ::= from <ELTONAME> <OPCALIAS> <OPCADICIONALTABLES> <OPCALIAS> ::= <VACIO> <OPCALIAS> ::= <OPCAS> <IDENTIFICADOR> <OPCADICIONALTABLES> ::= <VACIO> <OPCADICIONALTABLES> ::= <COMA> <ADICIONALTABLES> <ADICIONALTABLES> ::= <UNAADICIONALTABLES> <MASADICIONALTABLES> <MASADICIONALTABLES> ::= <VACIO> <MASADICIONALTABLES> ::= <COMA> <UNAADICIONALTABLES> <MASADICIONALTABLES> <UNAADICIONALTABLES> ::= <ELTOADICIONALTABLES> <UNAADICIONALTABLES> ::= outer <RESTOUNAADICIONALTABLES> <RESTOUNAADICIONALTABLES> ::= <ELTOADICIONALTABLES> <RESTOUNAADICIONALTABLES> ::= <PAR1> <ELTOADICIONALTABLES> <OPCADICIONALTABLES> <PAR2> <ELTOADICIONALTABLES> ::= <ELTONAME> <RESTOELTOADICIONALTABLES> <RESTOELTOADICIONALTABLES> ::= <VACIO> <RESTOELTOADICIONALTABLES> ::= <OPCAS> <IDENTIFICADOR> <OPCWHERECLAUSE> ::= <VACIO> <MASWHERECLAUSE> ::= <EXPRSQL> <OPCGROUPBYCLAUSE> ::= <VACIO> <OPCGROUPBYCLAUSE> ::= group by <RESTGROUPBYCLAUSE> <RESTGROUPBYCLAUSE> ::= <UNAGROUPBYCLAUSE> <MASGROUPBYCLAUSE> <MASGROUPBYCLAUSE> ::= <VACIO> <MASGROUPBYCLAUSE> ::= <COMA> <UNAGROUPBYCLAUSE> <MASGROUPBYCLAUSE> <UNAGROUPBYCLAUSE> ::= <ENTERO> <UNAGROUPBYCLAUSE> ::= <ELTOSEL> <OPCASCDESC> <OPCHAVINGCLAUSE> ::= <VACIO> <OPCHAVINGCLAUSE> ::= having <EXPRSQL> <OPCORDERBYCLAUSE> ::= <VACIO> <OPCORDERBYCLAUSE> ::= order by <UNAORDERBYCLAUSE> <MASORDERBYCLAUSE> <MASORDERBYCLAUSE> ::= <VACIO> <MASORDERBYCLAUSE> ::= <COMA> <UNAORDERBYCLAUSE> <MASORDERBYCLAUSE> <UNAORDERBYCLAUSE> ::= <ENTERO> <OPCASCDESC>

Page 48: IfxToJava2

48

<UNAORDERBYCLAUSE> ::= rowid <OPCASCDESC> <UNAORDERBYCLAUSE> ::= <ELTOSEL> <OPCASCDESC> <OPCINTOTEMPCLAUSE> ::= <VACIO> <OPCINTOTEMPCLAUSE> ::= into temp <IDENTIFICADOR> <OPCWITHNOLOG> <SENTENCIASQL> ::= <SENTENCIASTART> <SENTENCIASTART> ::= start <NOMBREBD> <SENTENCIASQL> ::= <SENTENCIAUNLOD> <SENTENCIAUNLOAD> ::= unload to <STRINGOVBLE> <OPCDELIMITER> <RESTOSENTUNLOAD> <RESTOSENTUNLOAD> ::= <SENTENCIASELECT> <RESTOSENTUNLOAD> ::= <VARIABLE> <SENTENCIASQL> ::= <SENTENCIAUNLOCK> <SENTENCIAUNLOCK> ::= unlock table <ELTONAME> <SENTENCIASQL> ::= <SENTENCIAUNPDATE> <SENTENCIAUPDATE> ::= update <RESTOSENTUPDATE> <RESTOSENTUPDATE> ::= statistics <OPCFORTABLE> <RESTOSENTUPDATE> ::= <ELTONAME> set <CLAUSULASET> <OPCWHERECLAUSULASET> <CLAUSULASET> ::= <PAR1> <ELTOSSEL> <PAR2> <CASO1CLAUSULASET> <CLAUSULASET> ::= <ASTERISCO> <CASO1CLAUSULASET> <CLAUSULASET> ::= <ELTONAME> <RESTOCLAUSUALSET> <RESTOCLAUSULASET> ::= <PTO> <ASTERISCO> <CASO1CLAUSULASET> <RESTOCLAUSULASET> ::= <PTO> <IDENTIFICADOR> <IGUAL> <CASO2CLAUSULASET> <RESTOCLAUSULASET> ::= <IGUAL> <CASO2CLAUSULASET> <CASO1CLAUSULASET> ::= <IGUAL> <RESTOCASO1CLAUSULASET> <RESTOCASO1CLAUSULASET> ::= <PAR1> <ELTOSCASO1CLAUSULASET> <PAR2> <RESTOCASO1CLAUSULASET> ::= <REFERECEDVALUES> <ELTOSCASO1CLAUSULASET> ::= <UNAELTOCASO1CLAUSULASET> <MASELTOCASO1CLAUSULASET> <MASELTOCASO1CLAUSULASET> ::= <VACIO> <MASELTOCASO1CLAUSULASET> ::= <COMA> <UNAELTOCASO1CLAUSULASET> <MASELTOCASO1CLAUSULASET> <UNAELTOCASO1CLAUSULASET> ::= <SENTENCIASELECT> //select ... <UNAELTOCASO1CLAUSULASET> ::= <EXPRSQL> <UNAELTOCASO1CLAUSULASET> ::= <REFRERENCEDVALUES> <RESTOUNAELTOCASO1CLAUSULASET> <RESTOUNAELTOCASO1CLAUSULASET> ::= <VACIO> <RESTOUNAELTOCASO1CLAUSULASET> ::= <MASMENOSPORENTRE> <EXPRSQLADICION> <MASEXPRSQLADICION> <CASO2CLAUSULASET> ::= <UNAELTOCASO2CLAUSULASET> <MASELTOCASO2CLAUSULASET> <MASELTOCASO2CLAUSULASET> ::= <VACIO> <MASELTOCASO2CLAUSULASET> ::= <COMA> <ELTONAME> <IGUAL> <CASO2CLAUSULASET> <UNAELTOCASO2CLAUSULASET> ::= <SENTENCIASELECT> <UNAELTOCASO2CLAUSULASET> ::= <EXPRSQL> <OPCWHERECLAUSULASET> ::= <VACIO> <OPCWHERECLAUSULASET> ::= where <RESTOOPCWHERECLAUSULASET> <RESTOOPCWHERECLAUSULASET> ::= current of <IDENTIFICADOR> <RESTOOPCWHERECLAUSULASET> ::= <EXPRSQL> <OPCFORTABLE> ::= <VACIO> <OPCFORTABLE> ::= for table <ELTONAME> <--------> <TIPODATOSQL> ::= serial <RESTO1DIM> <TIPODATOSQL> ::= text <RESTOTEXTBYTESQL> <TIPODATOSQL> ::= byte <RESTOTEXTBYTESQL> <TIPOADTOSQL> ::= <TIPOBASICO> <RESTOTEXTBYTESQL> ::= <VACIO> <RESTOTEXTBYTESQL> ::= in <RESTO2TEXTBYTESQL> <RESTO2TEXTBYTESQL> ::= table <RESTO2TEXTBYTESQL> ::= <IDENTIFICADOR> <NOMBREBD> ::= <VARIABLE> <NOMBREBD> ::= <CTE_CADENA>

Page 49: IfxToJava2

49

<ELTOSNAME> ::= <ELTONAME> <MASELTOSNAME> <MASELTOSNAME> ::= <VACIO> <MASELTOSNAME> ::= <ELTONAME> <MASELTOSNAME> <ELTONAME> ::= <OPCDATABASE> <PROPIETARIOSQL> <IDENTIFICADOR> <ELTONAME> ::= <PROPIETARIOSQL> <IDENTIFICADOR> <PROPIETARIOSQL> ::= <VACIO> <PROPIETARIOSQL> ::= <CTE_CAD> <PTO> <ELTOSSEL> ::= <ELTOSEL> <MASELTOSSEL> <MASELTOSSEL> ::= <VACIO> <MASELTOSSEL> ::= <COMA> <ELTOSEL> <MASELTOSSEL> <ELTOSEL> ::= <ELTONAME> <PTO> <IDENTIFICADOR> <ELTOSEL> ::= <IDENTIFICADOR> <CLAUSULAVALUES> ::= values <PAR1> <ELTOSCLAUSULAVALUES> <PAR2> <ELTOSCLAUSULAVALUES> ::= <UNAELTOSCLAUSULAVALUES> <MASELTOSCLAUSULAVALUES> <MASELTOSCLAUSULAVALUES> ::= <VAIO> <MASELTOSCLAUSULAVALUES> ::= <COMA> <UNAELTOSCLAUSULAVALUES> <MASELTOSCLAUSULAVALUES> <UNAELTOSCLAUSULAVALUES> ::= null <UNAELTOSCLAUSULAVALUES> ::= <EXPRCONSTANTESQL> <UNAELTOSCLAUSULAVALUES> ::= <RECORDREFERENCE> <RESTOVBLECLAUSULAVALUES> <RESTOVBLECLAUSULAVALUES> ::= <VACIO> <RESTOVBLECLAUSULAVALUES> ::= <PTO> <ASTERISCO> <RESTOVBLECLAUSULAVALUES> ::= thru <RECORDREFERENCE> <REFERENCEDVALUES> ::= <RECORDREFERENCE> <RESTOREFEENCEDVALUES> <RESTOREFEENCEDVALUES> ::= <VACIO> <RESTOREFEENCEDVALUES> ::= thru <RECORDREFERENCE> <RESTOREFEENCEDVALUES> ::= <PTO> <ASTERISCO> <EXPRSCONSTANTESQL> ::= <EXPRCONSTANTESQL> <MASEXPRCONSTANTESQL> <MASEXPRCONSTANTESQL> ::= <VACIO> <MASEXPRCONSTANTESQL> ::= <COMA> <EXPRCONSTANTESQL> <MASEXPRCONSTANTESQL> <EXPRCONSTANTESQL> ::= <CTE_CAD> <EXPRCONSTANTESQL> ::= user <EXPRCONSTANTESQL> ::= <DECIMAL> <EXPRCONSTANTESQL> ::= today <EXPRCONSTANTESQL> ::= current <MASCTECURRENT> <MASCTECURRENT> ::= <VACIO> <MASCTECURRENT> ::= <DATETIMEQUALIFIER> <EXPRCONSTANTESQL> ::= <DATETIMELITERAL> <EXPRCONSTANTESQL> ::= <INTERVALLITERAL> <EXPRCOLUMN> ::= <OPCARROBA> <ELTONAME> <PTO> <RESTOEXPRCOLUMN> <RESTOEXPRCOLUMN> ::= <IDENTIFICADOR> <OPCDIM> <RESTOEXPRCOLUMN> ::= rowid <OPCARROBA> ::= <VACIO> <OPCARROBA> ::= arroba <OPCDIM> ::= <VACIO> <OPCDIM> ::= <COR1> <ENTERO> <COMA> <ENTERO> <COR2> <OPCIGUAL> ::= <VACIO> <OPCIGUAL> ::= igual <OPCALL> ::= <VACIO> <OPCALL> ::= all

Page 50: IfxToJava2

50

<OPCAS> ::= <VACIO> <OPCAS> ::= as <OPCNOT> ::= <VACIO> <OPCNOT> ::= not <OPCNOTNULL> ::= <VACIO> <OPCNOTNULL> ::= not null <OPCFORTABLE> ::= <VACIO> <OPCFORTABLE> ::= for table <ELTONAME> <OPCMODEANSI> ::= <VACIO> <OPCMODEANSI> ::= mode ansi <OPCALLUNIQUEDISTICT> ::= <VACIO> <OPCALLUNIQUEDISTICT> ::= all <OPCALLUNIQUEDISTICT> ::= <UNIQUEDISTICT> <OPCUNIQUEDISTICT> ::= <VACIO> <OPCUNIQUEDISTICT> ::= <UNIQUEDISTICT> <UNIQUEDISTICT> ::= unique <UNIQUEDISTICT> ::= distinct <USINGINTO> ::= using <USINGINTO> ::= itno <OPCMASMENOS> ::= <VACIO> <OPCMASMENOS> ::= mas <OPCMASMENOS> ::= menos <SHAREEXCLUSIVE> ::= share <SHAREEXCLUSIVE> ::= exclusive <ONOFF> ::= on <ONOFF> ::= off <OPCCONSTRAINT> ::= <VACIO> <OPCCONSTRAINT> ::= constraint <ELTONAME> <OPCESCAPE> ::= <VACIO> <OPCESCAPE> ::= escape <CTE_CADENA> <OPCCLUSTER> ::= <VACIO> <OPCCLUSTER> ::= cluster <OPCPUBLICPRIVATE> ::= <VACIO> <OPCPUBLICPRIVATE> ::= public <OPCPUBLICPRIVATE> ::= private <OPCASCDESC> ::= <VACIO> <OPCASCDESC> ::= asc <OPCASCDESC> ::= desc <OPCWITHHOLD> ::= <VACIO> <OPCWITHHOLD> ::= with hold <OPCWITHREOPTIMIZATION> ::= <VACIO> <OPCWITHREOPTIMIZATION> ::= with reoptimization <OPCWITHNOLOG> ::= <VACIO> <OPCWITHNOLOG> ::= with no log

Page 51: IfxToJava2

51

<OPCDELIMITER> ::= <VACIO> <OPCDELIMITER> ::= delimiter <STRINGOVBLE> <OPCCOLUMNS> ::= <VACIO> <OPCCOLUMNS> ::= <PAR1> <COLUMNS> <PAR2> <COLUMNS> ::= <ELTOCOLUMNS> <MASCOLUMNS> <MASCOLUMNS> ::= <VACIO> <MASCOLUMNS> ::= <COMA> <ELTOCOLUMNS> <MASCOLUMNS> <ELTOCOLUMNS> ::= <IDENTIFICADOR> <-----------> <EXPRSQL> ::= <EXPRSQLSQLCONDICIONALOR> <MASEXPRSQLSQLCONDICIONALOR> <MASEXPRSQLSQLCONDICIONALOR> ::= <VACIO> <MASEXPRSQLSQLCONDICIONALOR> ::= or <EXPRSQLSQLCONDICIONALOR> <MASEXPRSQLSQLCONDICIONALOR> <EXPRSQLSQLCONDICIONALOR> ::= <EXPRSQLSQLCONDICIONALAND> <MASEXPRSQLSQLCONDICIONALAND> <MASEXPRSQLSQLCONDICIONALAND> ::= <VACIO> <MASEXPRSQLSQLCONDICIONALAND> ::= and <EXPRSQLSQLCONDICIONALAND> <MASEXPRSQLSQLCONDICIONALAND> <EXPRSQLSQLCONDICIONALAND> ::= <EXPRSQLNOT> <MASEXPRSQLNOT> <MASEXPRSQLNOT> ::= <VACIO> <MASEXPRSQLNOT> ::= not <EXPRSQLNOT> <MASEXPRSQLNOT> <EXPRSQLNOT> ::= <EXPRSQLIS> <MASEXPRSQLIS> <MASEXPRSQLIS> ::= <VACIO> <MASEXPRSQLIS> ::= is null <MASESPRSQLIS> <MASEXPRSQLIS> ::= is not null <MASESPRSQLIS> <EXPRSQLIS> ::= <EXPRSQLBETWEEN> <MASEXPRSQLBETWEEN> <MASEXPRSQLBETWEEN> ::= <VACIO> <MASEXPRSQLBETWEEN> ::= between <EXPRSQL> and <EXPRSQL> <MASEXPRSQLBETWEEN> <EXPRSQLBETWEEN> ::= <EXPRSQLIN> <MASEXPRSQLIN> <MASEXPRSQLIN> ::= <VACIO> <MASEXPRSQLIN> ::= in <PAR1> <RESTOEXPRSQLIN> <PAR2> <MASEXPRSQLIN> <RESTOEXPRSQLIN> ::= <EXPRSCONSTANTESQL> <RESTOEXPRSQLIN> ::= <SENTENCIASELECT> <EXPRSQLIN> ::= <EXPRSQLSQLRELACION> <MASEXPRSQLSQLRELACION> <MASEXPRSQLRELACION> ::= <VACIO> <MASEXPRSQLRELACION> ::= compigual <EXPRSQLRELACION> <MASEXPRSQLRELACIOM> <MASEXPRSQLRELACION> ::= compdesigual <EXPRSQLRELACION> <MASEXPRSQLRELACION> <MASEXPRSQLRELACION> ::= menor <EXPRSQLRELACION> <MASEXPRSQLRELACION> <MASEXPRSQLRELACION> ::= mayor <EXPRSQLRELACION> <MASEXPRSQLRELACION> <MASEXPRSQLRELACION> ::= menorigual <EXPRSQLRELACION> <MASEXPRSQLRELACION> <MASEXPRSQLRELACION> ::= mayorigual <EXPRSQLRELACION> <MASEXPRSQLRELACION> <EXPRSQLRELACION> ::= <EXPRSQLLIKE> <MASEXPRSQLLIKE> <MASEXPRSQLLIKE> ::= <VACIO> <MASEXPRSQLLIKE> ::= like <STRINGOVBLE> <OPCESCAPE> <MASEXPRSQLLIKE> <MASEXPRSQLLIKE> ::= matches <STRINGOVBLE> <OPCESCAPE> <MASEXPRSQLLIKE> <EXPRSQLLIKE> ::= <EXPRSQLADICION> <MASEXPRSQLADICION> <MASEXPRSQLADICION> ::= <VACIO> <MASEXPRSQLADICION> ::= mas <EXPRSQLADICION> <MASEXPRSQLADICION> <MASEXPRSQLADICION> ::= menos <EXPRSQLADICION> <MASEXPRSQLADICION> <EXPRSQLADICION> ::= <EXPRSQLMULTIPLY> <MASEXPRSQLMULTIPLY> <MASEXPRSQLMULTIPLY> ::= <VACIO> <MASEXPRSQLMULTIPLY> ::= por <EXPRSQLMULTIPLY> <MASEXPRSQLMULTIPLY> <MASEXPRSQLMULTIPLY> ::= entre <EXPRSQLMULTIPLY> <MASEXPRSQLMULTIPLY> <EXPRSQLMULTIPLY> ::= <EXPRSQLUNARIA> <EXPRSQLUNARIA> ::= exist <PAR1> <SENTENCIASELECT> <PAR2> <EXPRSQLUNARIA> ::= any <EXPRSQLUNARIA> <EXPRSQLUNARIA> ::= all <EXPRSQLUNARIA> <EXPRSQLUNARIA> ::= some <EXPRSQLUNARIA> <EXPRSQLUNARIA> ::= not <EXPRSQLUNARIA> <EXPRSQLUNARIA> ::= mas <EXPRSQLUNARIA> <EXPRSQLUNARIA> ::= menos <EXPRSQLUNARIA>

Page 52: IfxToJava2

52

<EXPRSQLUNARIA> ::= <EXPRSQLPRIMARIA> <EXPRSQLPRIMARIA> ::= <PARENTESIS1> <EXPRSQL> <PARENTESIS2> <EXPRSQLPRIMARIA> ::= <EXPRCOLUMN> <EXPRSQLPRIMARIA> ::= <EXPRCONSTANTESQL> <EXPRSQLPRIMARIA> ::= <EXPRSQLLLAMADAFUNCION> <EXPRSQLPRIMARIA> ::= <EXPRAGREGADA> <EXPRSQLPRIMARIA> ::= <VARIABLE> <---------> <IDENTIFICADOR> ::= identificador <CTE_CADENA> ::= cadena <AROBA> ::= arroba <VACIO> ::= vacio <FICHERO> ::= <CTE_CAD> <CTE_CAD> ::= <COMILLAS> cadenacar <COMILLAS> <COMILLAS> ::= comillas <GUION> ::= guion <LETRA> ::= letra <PTO> ::= pto <PAR1> ::= par1 <PAR2> ::= par2 <COMA> ::= coma <COR1> ::= cor1 <COR2> ::= cor2 <ASTERISCO> ::= asterisco <CONCAT> ::= barraverticaldoble

El analizador sintáctico implementa esta gramática. La gramática no es LL1 en todos los casos y estas situaciones son resueltas durante la codificación. Los casos que no cumplen LL1 son:

Al hacer referencia al nombre de una elemento de una tabla. Esto se da en varias ocasiones dentro de la definición sintáctica:

Dentro de la definición de tipos de datos en:

like <PROPIETARIO> <IDENTIFICADOR> <PTO> <IDENTIFICADOR>

like <PROPIETARIO> <IDENTIFICADOR> <PTO> <ASTERISCO>

Dentro de la sentencia INITIALIZE en:

<PROPIETARIO> <IDENTIFICADOR> <PTO> <ULTUNARESTOLIKEINITIALIZE>

Dentro de la sentencia VALIDATE en:

<PROPIETARIO> <IDENTIFICADOR> <PTO> <RESTOUNAVALIDATE>

En todas las sentencias SQL al hacer referencia al nombre de una tabla o al campo de una tabla.

Todos estos casos no son ni siquiera LL3 ya que para determinar si se esta recuperando el nombre de una tabla o el propietario se debe leer tres tokens: un identificador, punto, e identificador y en función del siguiente (punto o vació) y se podrá saber que elemento se esta tratando.

En las sentencias END, EXIT, OPEN, CLOSE y CONTINUE se ha tenido cuidado al definir las producciones de su definición sintáctica para evitar no fuese LL1. La única sentencia que debe ser contemplada y tratada en el sintáctico para evitar problemas es: END MAIN

Sentencia IF. Se soluciona durante el sintáctico y al generar código de tal forma que se anídale ELSE con el ultimo IF

Dentro de la sentencia REPORT, en la sección OUTPUT al tratar las dimensiones de las paginas:

<PAGEDIMENSION> ::= top of page <OPCIGUAL> <CTE_CAD>

Page 53: IfxToJava2

53

<PAGEDIMENSION> ::= top margin <OPCIGUAL> <ENTERO>

No es LL1 pero si LL2 tratado directamente por el analizador sintáctico.

Se dan otros casos, que son controlados dentro del sintáctico/semántico, debido a la posibilidad de que ciertas palabras reservadas se puedan utilizar como identificadores.

SEMANTICA, TABLA DE SIMBOLOS, Y MANEJO DE ERRORES

Como se comento, al definir los componentes del traductor y, dado que partimos de ficheros fuente sintáctica y semánticamente correctos se podría, erróneamente, creer que estos elementos del traductor no son precisos. A lo largo de los diferentes puntos de ésta sección se procederá a estudiar estos componentes y durante ese proceso de verá con claridad la necesidad de los mismos.

ANALIZADOR SEMANTICO

El analizador semántico, como su nombre indica, permite añadir reglas semánticas al traductor. Éste es preciso por muchas razones, a continuación se detallan algunas de ellas:

Permite controlar situaciones en las cuales la definición sintáctica no es LL1, como el caso de la sentencia END MAIN.

Valores por defecto en la definición de variables. En la definición de las variables de Informix-4GL y campos de la base de datos Informix permite cierta libertad como en el caso de los tipos de datos CHAR, DECIMAL, etc., en los cuales de forma opcional se pueden dejar sin especificar la dimensión de los mismos sin que esto implique ningún error sintáctico.

A la hora de traducir estas definiciones a JAVA no se plantea ningún problema ya que uno se pasará a String y el otro a Double ó BigDecimal y en ningún caso hay que indicar la dimensión.

Si lo que se define es un campo de una tabla, dependiendo para qué gestor de bases de datos, puede ser preciso especificar la dimensión con lo cual será preciso aplicar la semántica de Informix en el momento de la traducción para aplicar los valores por defecto.

Valores por defecto en sentencias SQL. Existen sentencias SQL en las que Informix permite omitir, a la hora de la utilización de las mismas, ciertas definiciones, tales como: FETCH [next], SELECT [all], ORDER BY [asc], etc.

A la hora de generar código de estas sentencias para otros gestores de bases de datos y con objeto de garantizar el correcto funcionamiento, sobre ellos, se aplica semántica y se añade la acción que por defecto que aplica Informix en el caso de que se omita esta en la declaración de la sentencia.

En la inicialización de variables en el código objeto generado. Aunque Informix no obliga a inicializar las variables antes de utilizarlas en el código, JAVA si. Para determinar el valor a asignar se aplican reglas semánticas. El valor asignado dependerá del tipo de dato que se haya definido.

En la asignación de valores a variables. La sentencia LET de Informix permite asignar valores a variables de programa, en ciertos casos, a la hora de realizar la traducción, esta no se puede hacer de forma directa debido a que la expresión resultante no es reconocida por JAVA. En estos casos se precisa hacer alguna conversión de la expresión original. Los casos más destacados son los relativos al procesamiento de fechas, así una expresión que devuelve una fecha en Informix-4GL se le deben aplicar reglas semánticas para convertirla a formato JAVA (java.sql.Date o java.sql.Timestamp), Ej.:

Codito fuente Informix-4GL: let fecha = today

Código objeto JAVA: fecha = new Date(new java.util.Date().getTime()) ;

Al tratar las expresiones 4GL. Al igual que ocurre con las expresiones SQL las operaciones sobre alguna expresión 4GL no siempre pueden ser traducidas directamente sin aplicar reglas semánticas de conversión o casting sobre algún operando, ya que aunque el lenguaje original (Informix) lo permita el final (JAVA) puede que no.

Page 54: IfxToJava2

54

Tratamiento de las expresiones SQL. Si las expresiones que aparecen en el código fuente se aplicasen sobre un gestor de bases de datos Informix no sería necesario hacer nada, pero como se pretende aplicarlas sobre otros gestores es preciso saber el tipo de dato de los operados para:

Saber si la operación es permitida por el gestor de bases de datos destino.

Hay que hacer algún tipo de casting o conversión.

Hay que redefinir la forma en que se aplica el operador.

Así, por ejemplo, Informix permite realizar operaciones aritméticas sobre fechas (sumas y restas). Para el resto de gestores, si lo permiten, se necesita aplicar alguna regla semántica que permita definir la operación de tal forma que sea valida para el gestor de bases de datos destino. Ej.:

Código fuente Informix-4GL: select fecha - campo4 into dos from prueba1

Código objeto JAVA para SqlServer: executeQuery("select datediff(dd,campo4 ,{d '"+fecha+" '} ) from prueba1 ");

Otro caso es la interpretación de los días de la semana ya que cada gestor de bases de datos y, dependiendo del lenguaje, puede utilizar su propia codificación numérica para el día de la semana la cual puede no tener el mismo significado que la codificación que realiza Informix.

Por, al menos, las razones indicadas es preciso detectar, mantener, y propagar los tipos de datos de las constantes, variables y expresiones dentro del analizador con objeto de poder aplicar las reglas semánticas.

TABLA DE SIMBOLOS

En la tabla de símbolos se almacenan la información necesaria para poder aplicar las reglas semánticas durante el proceso de traducción.

La estructura de la tabla de símbolos es la de una tabla HASH donde el elemento clave es el nombre del identificador y el campo de información esta formado por una clase que contiene:

Nombre, identificador del elemento.

Tipo, contiene el tipo de dato del elemento.

Ámbito. Indica el ámbito del elemento. Los ámbitos de las variables pueden ser:

GLOBAL. Si la variable esta definida en el módulo �globals� lo cual indica que puede ser referenciada desde cualquier el módulo de los que conforman el programa multimódulo.

MÓDULO. Solo puede ser referenciada desde el módulo en el cual es declarada.

LOCAL. Su ámbito es solo el método en el cual se declara.

A la hora de buscar un elemento en la tabla de símbolos primero se mira si esta definida en el método actual, seguidamente si esta definida a nivel de módulo y en caso de no ser así se comprueba si esta definida en la sección �globals�

Módulo. Indica en que módulo se definió el elemento.

Como se indicó en el semántico es preciso saber el tipo de dato del que son las variables definidas en el código fuente y por añadidura es también el ámbito ya que una variable con igual nombre de identificador puede estar definida en dos puntos del programa y ser de diferente tipo y/o ámbito.

Los valores se almacenan en la tabla de símbolos en el momento de su declaración. Informix-4GL es bastante restrictivo en cuanto a los puntos en los cuales se pueden definir variables lo cual facilita el manejo de la tabla de símbolos. Solo se pueden definir variables en la sección �globals� (ámbito Global), al principio del programa antes de la sentencia MAIN (ámbito módulo) y dentro del MAIN y en las funciones y reports justo al principio de los mismos (ámbito local). Las variables de ámbito global o tipo módulo se mantienen en la tabla de símbolos durante todo el proceso de

Page 55: IfxToJava2

55

traducción, del módulo en curso, sin embargo las variables locales solo durante el trozo de código en el que pueden ser utilizadas.

La tabla de símbolos puede ser accedida dentro del analizador en cualquier momento siendo los puntos más comunes en las operaciones sobre expresiones y a la hora de hacer asignaciones de valores a variables.

No toda la información es mantenida en la tabla de símbolos, cuando es preciso saber el tipo de dato de un campo de una tabla de la base de datos puede ser preciso hacer una consulta directamente al gestor ya que se puede estar accediendo a una tabla que no fue creada en el mismo fichero que se esta procesando.

MANEJO DE ERRORES

El manejo de errores se utiliza dentro del proceso de traducción para indicar al usuario aquellos warnings o errores que se pueden producir como consecuencia de la ejecución del código objeto generado.

Si el código generado va ser ejecutado sobre un gestor de bases de datos Informix no se contempla que se pueda producir ningún error ya que todas las sentencias ya han sido escritas para ser ejecutadas sobre el mismo. En cambio como se puede generar código para ser ejecutado sobre otros gestores de bases de datos y no todas las sentencias SQL de Informix son totalmente compatibles con las que proporcionan estos se avisa de las limitaciones o problemas que pueden aparecer. Estos avisos están orientados a indicarle al usuario que revise el código objeto generado para que tome las acciones que considere oportunas.

Algunos ejemplos de errores que se pueden mostrar son:

Warning: Sentencia create audit no generada

Warning: Sentencia PREPARE, revisar sintaxis SQL

Se han añadido mensajes adicionales para contemplar problemas en el código fuente debido a algún error de sintaxis. Estos errores no se deberían producir ya que se parte de programas sintácticamente correctos.

GENERACIÓN DE CÓDIGO

El generador de código se encarga de generar las sentencias JAVA correspondientes a cada sentencia 4GL que aparece en el código fuente.

El diseño del generador de código tiene dos características relevantes:

Fácilmente ampliable sin que para ello sea preciso modificar el resto de módulos del traductor. Siguiendo la filosofía de PATRON ESTRATEGIA se han creado módulos independientes y cada módulo procesa las sentencias específicas asociadas a cada gestor de bases de datos. En función de para que gestor se este ejecutando el traductor instanciará uno u otro módulo.

Si a futuro se plantease la traducción del código fuente para un nuevo gestor de bases de datos sería suficiente con crear el módulo que procese las sentencias SQL de dicho lenguaje.

Utilización de buffers intermedios entre el generador de código y el fichero de código objeto generado. Dicho de otra forma la generación de código asociado a una sentencia se va haciendo por trozos no produciendo un resultado final sobre el fichero destino hasta que se haya procesado ésta en su totalidad.

Esta forma de operar del generador de código permite una versatibilidad necesaria a la hora de generar código objeto. Seguidamente se muestran un par de ejemplos, simplificados, con objeto de entender mejor el concepto:

EJEMPLO1: TRATAMIENTO DE EXPRESIONES

Código fuente: select fecha - today from prueba1

Código objeto: ResultSet ASG_r8 = ASG_st8.executeQuery("select datediff(dd,dateadd(dd,0, datediff(dd,0,getdate())) ,{d '"+ fecha +"'} ) from prueba1 ");

Page 56: IfxToJava2

56

Pasos en la traducción:

Paso1: Se Inicializa buffer y elige el primero

Paso2: Se guardar en el primer buffer: �select�

Paso3: Pasar al buffer siguiente y almacenar: �fecha�

Se determina que el operando es de tipo fecha

Paso4: Se obtiene el tipo de operador

Pasar al buffer siguiente y almacenar : �today�

Se determina que es una constante tipo fecha

Paso5: Se pasa al buffer siguiente y se almacena en él: �from prueba1�

Paso6: Se genera la sentencia objeto en función de la información guardada en los buffers.

La generación de código resultante, en este caso para SqlServer, se basa en la sentencia original, dividida por secciones, y en la información sobre los operadores para generar una instrucción valida para el gestor de bases de datos destino. Como se puede ver el aplicar el operador sobre los operandos implica añadir código específico para el gestor de bases de datos SqlServer y reorganizar los operandos lo cual si fuese una traducción lineal y directa no se podría hacer.

Por otro lado, y como es de suponer, se aplican reglas semánticas para determinar los tipos de datos de los operandos y si el operador se puede aplicar sobre éstos.

EJEMPLO 2: TRATAMIENTO DE CONSTRAINTS

Código fuente: alter table tabla1 add constraint unique (campo1,campo2) constraint constr4

Código objeto: ASGdb.exeUpdate("alter table tabla1 add constraint constr4 unique ( campo1 , campo2)� );

Pasos en la traducción:

Paso1: Inicializar buffer y elegir el primero

Paso2: Almacenar en buffer = �alter table tabla1 add constraint�

Paso3: Pasar al buffer siguiente y almacenar = �unique (campo1,campo2)�

Paso4: Coger el siguiente buffer y guardar en él = �constr4�

Paso5: Pasar la información de los bufferes al fichero que mantiene el código objeto, para ello:

Se envía a fichero buffer 1

Se comprueba si ha definido el nombre del constraint, en tal caso se envía a fichero el contenido del buffer 3

Se envía a fichero el contenido del buffer2

Este es un ejemplo simplificado y permite ejemplificar el tratamiento por partes de las sentencias a la hora de genera código, el hacerlo así permite trasformar la sentencia llegando a reorganizar parte de la misma como ocurre en este caso con el nombre del constraint que en la sentencia original aparece al final y sin embargo en la generada en medio de la misma.

Este sistema que se ha planteado para la generación de código tiene múltiples ventajas:

Se desvincula la generación de la sentencia objeto del procesamiento del fichero que contendrá el código objeto. Al final del tratamiento de una sentencia se tendrá en un único buffer la sentencia objeto completa siendo los métodos diseñados para el tratamiento del

Page 57: IfxToJava2

57

fichero objeto los encargados de: pasar el contenido del buffer a disco, aplicar las indentaciones y saltos de línea precisos y liberar los bufferes utilizados.

Se añade un alto nivel de abstracción y ocultación ya que en punto de programa obtenemos el código generado de los elementos de la sentencia sin tener que preocuparnos de cómo se obtienen estos.

TRATAMIENTO DE SENTENCIAS DE INFORMIX-4GL En este apartado se analizarán las sentencias de programa, y se indicará la solución adoptada para pasar de código fuente 4GL a objeto JAVA. El enfoque es diferente al que se hace para el tratamiento de las sentencias SQL ya que la traducción de las sentencias 4GL será siempre la misma independientemente del gestor de bases de datos.

Las sentencias que se tratan en este proceso son:

De definición del módulo principal de programa.

De manejo de funciones.

De control de flujo.

De definición y uso de variables.

De definición de menús.

SENTENCIAS DE DEFINICIÓN DEL MÓDULO PRINCIPAL DE PROGRAMA

Informix-4GL permite realizar programas monomódulo y multimódulo y aparte permite definir un módulo especial de definición de variables globales.

Un programa monomódulo esta formado por un único fichero de código fuente, puede constar de los bloques indicados en la figura que se muestra a continuación, y como mínimo contendrá el bloque MAIN.

Un programa multimódulo estará formado por varios ficheros de código fuente. Entre ellos habrá un único fichero que contenga el bloque MAIN. El resto de los ficheros que forman parte del programa pueden estar formados por todas las secciones de un módulo de programa a excepción del bloque MAIN.

La sección GLOBALS permite definir variables globales a todos los módulos. El código asociado a esta sección se puede definir en cada uno de los módulos que tenga que acceder a las variables globales o bien en un módulo independiente y ser referenciado desde esta sección.

El esquema básico de un módulo de programa se muestra en la siguiente figura:

Page 58: IfxToJava2

58

Figura 6: Estructura básica de un módulo de programa

Con la idea básica de las secciones de un módulo de programa, la posibilidad de que un programa puede estar constituido por más de un módulo y el valor añadido, que se quiere aportar en este proyecto, de proporcionar un interface gráfico, estilo WINDOWS, a los programas generados, el estudio de la traducción del módulo principal de programa se enfoca desde dos puntos de vista:

Generación código modo texto o modo grafico.

Tratar programas monomódulo o multimódulo.

El módulo MAIN es el único que es obligatorio en un programa. En el momento de traducir esta sección a código objeto JAVA ya se está definiendo el módulo principal del mismo lo que implica definir un programa con todas sus secciones: imports, definición de clase principal, método MAIN, extents, etc.

A nivel esquemático el bloque MAIN de un programa escrito en Informix-4GL tiene la estructura:

MAIN <SENTENCIAS> END MAIN

Con este simple código se define el módulo mínimo de programa principal.

Pasar esta sentencia a código objeto JAVA es más complejo debido a que JAVA es un lenguaje orientado a objetos y es necesario definir una clase en la que crear los métodos. A nivel esquemático será:

<sección imports>

public class NOMBRE_CLASE <sección extents> {

<definiciones añadidas> public static void main(String argv[]) throws Exception {

<sentencias añadidas> <SENTENCIAS>

} }

SECCION GLOBALS

DEFINICION VARIABLES

BLOQUE MAIN

FUNCIONES y REPORTS

SECCION DATABASE

Page 59: IfxToJava2

59

Viendo esta traducción, la cual no mantiene correspondencia entre las sentencias de código fuente y sentencias de código objeto, cabe aclarar varios puntos:

La sentencia MAIN � END MAIN se transforma en:

public static void main(String argv[]) throws Exception {}

Esta transformación es lógica ya que es la forma en la que JAVA define el método principal. Cabe destacar:

Este método se define con un argumento para la recepción de los parámetros. Informix-4GL aunque no defina ningún argumento en el MAIN si los puede recibir, utiliza para ellos funciones propias del lenguaje como: arg_val().

Se añade a la definición del MAIN: throws Exception con objeto de indicar que aquellas excepciones que no se controlan se manden a consola. Informix-4GL viene preparado para el manejo de errores sobre todo en lo relacionado con el manejo de sentencias SQL pero como JAVA es mucho más potente, en este aspecto, es preciso adaptar los programas generados al uso de excepciones.

La sección imports que contiene las clases necesarios se añaden justo al principio. Los imports que podrán llegar a utilizarse serán conocidos de antemano y variarán dependiendo del tipo de programa que se este generando. Evidentemente, y al no poder controlar de antemano todas las situaciones y requerimientos del código fuente, es probable que se importen clases que no se usen.

Se define el nombre de la clase principal. El nombre de la clase coincidirá con el nombre del fichero fuente (sin extensión) y éste mismo nombre también se utilizará para el fichero de código objeto.

Definición de variables de módulo. Puede ser necesario definir alguna variable estática nueva y accesible desde cualquier parte del programa para mantener la equivalencia entre código fuente y objeto. Un caso bastante claro es definir una variable que mantendrá, durante todo el programa, la conexión con la base de datos.

Se añaden llamadas a métodos antes del inicio de las sentencias de programa. Al igual que la definición de variables de tipo módulo son métodos añadidos que permiten la ejecución de los programas generados. Los más típicos son los encargados de establecer la conexión con la bases de datos como:

ASGcondb.cargaparamcon(), que se encarga de cargar en memoria los parámetros de conexión con la base de datos.

ASGcondb = new AccesDB("datos") que establece la conexión con la base de datos.

GENERACIÓN DE CÓDIGO MODO TEXTO O GRÁFICO

A continuación se muestra, con un ejemplo, las principales variantes a la hora de generar código objeto JAVA dependiendo de si el programa final va o no a proporcionar interface grafico. En ambos casos se muestran los elementos básicos y mínimos para generar un programa en JAVA equivalente a uno escrito en Informix-4GL.

Cuadro 1: Código fuente mínimo de un programa Informix-4GL

main display "hola mundo" end main

hola.4gl

Page 60: IfxToJava2

60

Cuadro 2: Relación entre código objeto modo texto y modo gráfico

Observando la figura anterior, cuyo código es el resultado de aplicar el traductor creado bien para generar código texto o gráfico, se pueden observar varias diferencias en el modo grafico respecto al modo texto:

La clase principal extiende la clase JApplet. Se extiende ésta y no otra debido a que los programas, gráficos, generados están pensados para poder ejecutarse como una aplicación independiente o bien como un Applet desde un explorador Web.

Se define una variable estática ASGarea que será el contenedor sobre el cual se muestren todos los elementos, gráficos o no, de la aplicación.

El método principal, main, solo tiene una instrucción que se encarga de llamar al método run de la clase Console.

La clase Console definida en el paquete ASGgrafico es la que permite que un mismo programa pueda se lanzado como aplicación independiente o como un Applet.

El método init inicializa todos los elementos del entorno gráfico inicial.

El método ASGmain es el equivalente al método main de los programas diseñados para ser ejecutados en modo texto y contendrá todas las sentencias, del módulo main, traducidas del programa original.

El resultado de la ejecución del programa �hola�, tanto el original en Informix-4GL como los generados, a partir del traductor creado, se muestra en las siguientes figuras:

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class hola { static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGarea.append("hola mundo" +"\n"); } }

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; import javax.swing.*; import java.awt.*; import ASGgrafico.Console; public class hola extends JApplet { private static AccesDB ASGcondb = null; private static JTextArea ASGarea = new JTextArea(33,70); public static void main(String argv[]) throws Exception { Console.run(new hola(),800,600); } public void init() { Container ASGcp = getContentPane(); ASGcp.setLayout(new FlowLayout()); ASGarea.setEditable(false); ASGcp.add(new JScrollPane(ASGarea)); ASGarea.setText(""); try{ ASGmain(); } catch (Exception e ) {} } public void ASGmain () throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGarea.append("hola mundo" +"\n"); } }

hola.java

Page 61: IfxToJava2

61

Figura 7: Ejecución de la aplicación �hola.4gl� sobre Informix

Figura 8: Resultado de la ejecución del programa �hola.java� como aplicación modo texto

Page 62: IfxToJava2

62

Figura 9: Ejecución del programa �hola.java� como aplicación gráfica

Figura 10: Ejecución del programa �hola.java� como aplicación Web

Page 63: IfxToJava2

63

PROGRAMAS MULTIMÓDULO

Las principales diferencias, a la hora de aplicar el proceso de traducción, de un programa multimódulo con respecto a los monomódulo, son:

Definición de las variables añadidas en el proceso de traducción. Las variables ASGcondb y ASGarea deben de estar accesibles desde cualquiera de los módulos del programa con lo cual no pueden estar definidas en el módulo MAIN (monomódulo).

La solución adoptada es definir este tipo de variables en un módulo independiente y accesible desde todo aquellos que conforman el programa. Se creará un módulo llamado: ASGglobals_<nombre_módulo> con estas variables, de tipo estático, garantizando así que mantengan el valor y la accesibilidad entre módulos. El acceso a las mismas será:

Monomódulo. ASGcondb.<método>

Multimódulo: ASGglobal_<nombre_módulo>.Asgcondb.<método>

Acceso a métodos definidos en otros módulos. Para ello será preciso indicar antes del nombre de método el nombre de módulo, Ej.: módulo1.fx1 () en lugar de fx1().

Para poder saber el nombre del módulo en el que esta definido un método será preciso aplicar un proceso previo que identifique en que módulo está definida cada función. Habrá que simular algo parecido a la definición del �makefile� y el proceso make en Informix-4GL.

Cuadro 3: Makefile y ASGmakefile

.SUFFIXES: .4go .4gl .4gl.4go: @(echo 'Compilando $*' ; cd `dirname $<` ; fglpc $< ) PACTINV= mbuscom.4go\ mbuscoma.4go\ mcar.4go\ mcript.4go\ mdichlp.4go\ mf2.4go\ mfgl.4go\ mhelp.4go\ mimpre.4go\ uactinv.4go pactinv.4gi: $(PACTINV) makefile @echo 'Linkando pactinv.4gi' ; cat $(PACTINV) > pactinv.4gi � PCALPME=mblosem.4go\ mcalemp.4go\ mcar.4go\ mcript.4go\ mf2.4go\ mfgl.4go\ mhelp.4go\ mhlpte1.4go\ mlinque.4go\ mlispan.4go\ mlog.4go\ msanque.4go\ mbloext.4go\ mcalpme.4go\ ucalpme.4go\ pcalpme.4gi: $(PCALPME) makefile @echo 'Linkando pcalpme.4gi' ; cat $(PCALPME) > pcalpme.4gi

multi1= multi2.4gl multi3.4gl multi4.4gl multi5.4gl exe:multi1

multi21= multi11.4gl multi12.4gl multi13.4gl multi14.4gl exe:multi21

makefile ASGmakefile

Page 64: IfxToJava2

64

Siguiendo el caso mostrado en el cuadro anterior, el cual mantiene una similitud con la forma en que Informix trata los programas multimódulo, por cada programa multimódulo JAVA que se quiere generar se han de añadir varias entradas al fichero ASGmakefile. Estas entradas son:

Primero el nombre del módulo principal del programa multimódulo seguido del símbolo igual (=). El módulo principal es aquel que contiene el MAIN.

Tantas líneas como módulos que formen parte del programa excluyendo el módulo principal.

Y por último el TAG "exe:" seguido del módulo principal del programa. Este nombre será el utilizado para crear el módulo principal del programa JAVA.

Por cada módulo 4GL se creará un módulo JAVA. Se creará, también, un módulo adicional que contenga las variables a las cuales se puede hacer referencia desde cualquiera de los módulos del programa.

El fichero ASGmakefile puede contener información relativa a múltiples programas multimódulo.

La única restricción que tienen todos los módulos que forman parte de un programa multimódulo es que no puede haber más de una función con el mismo nombre aunque sea en módulos diferentes. Esto no causa ninguna pega en el proceso de traducción ya que esta misma restricción también la impone Informix-4GL.

El proceso de traducción de programas multimódulo sigue los siguientes pasos:

Localiza, del fichero ASGmakefile, todos los módulos de los que consta el programa y dentro de cada uno de estos todas las funciones.

Las funciones son añadidas a la tabla de Símbolos.

Recorre todos los módulos indicados en el ASGmakefile y comprueba si es preciso aplicar el proceso de traducción.

Es preciso �retraducir� el módulo si la fecha del fichero JAVA es anterior a la del fichero 4GL.

Aplica el proceso de traducción sobre los módulos. El último módulo que se procesa es el que contiene el bloque MAIN.

El último paso, para poder ejecutar el programa es compilar el módulo principal (javac módulo_ppal.java) y luego lanzar su ejecución (java módulo_ppal). Al compilar el módulo principal serán automáticamente compilados todos aquellos otros módulos precisos (según el comportamiento general de JAVA).

En el siguiente cuadro se muestran un ejemplo completo de programa multimódulo tanto en código fuente, Informix-4GL, como en código objeto, JAVA, generado. Estos módulos están definidos en el fichero ASGmakefile anterior y corresponden al programa: multi1.

Page 65: IfxToJava2

65

Cuadro 4: Ejemplo módulo principal de programa multimódulo

Cuadro 5: Ejemplo de módulo de programa multimódulo

function fx2(dos) define dos, bis smallint, bix2 char(20), tres, cuatro char(20) , cinco decimal(2,0) define dosbis integer let dosbis = 3 + fx3(dos) display "En funcion fx2: " ,dosbis display "Parametro recibido fx2: ",dos end function

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class multi2 { static void fx2(int dos) { int bis; String bix2; String tres; String cuatro; double cinco; int dosbis ; dosbis = 3 + multi3.fx3 ( dos ) ; System.out.println("En funcion fx2: " + dosbis ); System.out.println("Parametro recibido fx2: " + dos ); } }

multi2.4gl multi2.java

database datos define uno smallint main define uno smallint let uno = 1 message "En main: " , uno call fx(uno) call fx2(uno) message "En main tras vuelta funcion: " , uno end main function fx(dos) define dos smallint, tres integer let uno = 2 let tres = uno + dos; display "En funcion fx: " ,uno display "Parametro recibido fx: ",dos end function

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class multi1 { static int uno ; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGglobal_multi1.ASGcondb = new AccesDB("datos");

ASGglobal_multi1.ASGcondb.HayTransac(); int uno ; uno = 0; uno = 1 ; System.out.println("En main: " + uno ); fx ( uno ) ; multi2.fx2 ( uno ) ; System.out.println("En main tras vuelta funcion: " + uno ); } static void fx(int dos) { int tres; uno = 2 ; tres = uno + dos ; System.out.println("En funcion fx: " + uno ); System.out.println("Parametro recibido fx: " + dos ); } }

multi1.4gl multi1.java

Page 66: IfxToJava2

66

Cuadro 6: Ejemplo de módulo de programa multimódulo

Además de estos módulos se crea un 4º módulo con código JAVA llamado: ASGglobal_multi1.java con el siguiente código:

import ASGdb.*;

class ASGglobal_multi1 {

static AccesDB ASGcondb = null;

}

Este módulo contiene todas aquellas variables que pueden ser accedidas desde cualquiera de los módulos de programa.

EL MÓDULO GLOBALS

A través de la sentencia GLOBALS se pueden definir variables que son accesibles desde cualquiera de los módulos que conforman el programa y tienen ámbito global. Esta sentencia tiene dos posibles formas de definición: explicita de las variables o bien hacer referencia a un módulo (4GL) que contenga su definición. A continuación se muestra un ejemplo de cada una.

Definición explicita:

globals define valid char(1), impre char(50), nimp decimal(2,0) end globals

Definición haciendo referencia a un fichero:

globals "globales.4gl"

Donde el fichero tendrá una sentencia GLOBALS utilizando la definición explícita.

La forma de traducir esta sentencia de tal forma que se garantice que la definición de las variables es accesible desde cualquier módulo del programa es a través de otro módulo el cual contenga la declaración. Las variables dentro de este módulo se definirán de tipo estático consiguiendo así tengan el comportamiento de variables globales a todos los módulos.

A continuación se muestran dos ejemplos de la traducción de un programa Informix-4GL a JAVA. En el primero se utiliza la definición explicita y en el segundo haciendo referencia a un fichero.

function fx3(tres) define tres smallint define tresbis integer let tresbis = 3; display "En funcion fx3: " ,tresbis display "Parametro recibido fx3: ",tres return tresbis end function

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class multi3 { static int fx3(int tres) { int tresbis ; tresbis = 3 ; System.out.println("En funcion fx3: " + tresbis ); System.out.println("Parametro recibido fx3: " + tres ); return tresbis ; } }

multi3.4gl multi3.java

Page 67: IfxToJava2

67

Cuadro 7: Ejemplo de bloque de programa globals

En este caso el nombre del módulo se crea en función del nombre del módulo MAIN con un prefijo: ASGglobals. El acceso a las variables globales en el código objeto JAVA se hace utilizando como prefijo el nombre del módulo en el cual están definidas. Para determinar, en tiempo de traducción, si se trata de una variable global o bien una tipo módulo o local se utiliza la tabla de símbolos.

database datos globals define uno, dos, tres integer, cuatro decimal(2,0) define cinco char(20) end globals define uno integer main define uno integer let uno = 1 let dos = 2 display "MAIN= Variable ambito módulo(uno): ",uno call fx() call fx2(uno) end main function fx() let uno = 3 display "FX= Variable ambito módulo(uno): ",uno display "FX= Variable ambito global(dos): ",dos end function function fx2(dos) define dos integer display "FX2= parametro(variable uno tipo módulo; uno): ",dos display "FX2= valor de variable tipo módulo(uno): ", uno end function

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class modglobal { static int uno ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); uno = 0; uno = 1 ; ASGglobals_modglobal.dos = 2 ; System.out.println("MAIN= Variable ambito módulo(uno): " + uno ); fx ( ) ; fx2 ( uno ) ; } static void fx() { uno = 3 ; System.out.println("FX= Variable ambito módulo(uno): " + uno ); System.out.println("FX= Variable ambito global(dos): " + ASGglobals_modglobal.dos ); } static void fx2(int dos) { System.out.println("FX2= parametro(variable uno tipo módulo; uno): " + dos ); System.out.println("FX2= valor de variable tipo módulo(uno): " + uno ); } }

modglobal.4gl modglobal.java

class ASGglobals_modglobal{ static int uno , dos , tres; static double cuatro; static String cinco; }

ASGglobals_modglobal.java

Page 68: IfxToJava2

68

Cuadro 8: Ejemplo módulo de programa globals

En este caso como se hace referencia a un nombre de fichero de forma explicita se creará un módulo JAVA que se nombre de igual forma que el módulo original.

En la sección: Ámbito de variables, se explicará con más detalle la definición, utilización y traducción de este tipo de variables.

En el caso de que se este utilizando la sección globals con programas multimódulo se han de tener en cuenta varias cosas:

Cada módulo que quiera acceder a las variables globales debe indicarlo a través de la sentencia GLOBALS, bien de forma explicita o través de un fichero (implícita).

database datos globals �globals.4gl� define uno integer main define uno integer let uno = 1 let dos = 2 display "MAIN= Variable ambito módulo(uno): ",uno call fx() call fx2(uno) end main function fx() let uno = 3 display "FX= Variable ambito módulo(uno): ",uno display "FX= Variable ambito global(dos): ",dos end function function fx2(dos) define dos integer display "FX2= parametro(variable uno tipo módulo; uno): ",dos display "FX2= valor de variable tipo módulo(uno): ", uno end function

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class modglobal2 { static int uno ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); uno = 0; uno = 1 ; globals.dos = 2 ; System.out.println("MAIN= Variable ambito módulo(uno): " + uno ); fx ( ) ; fx2 ( uno ) ; } static void fx() { uno = 3 ; System.out.println("FX= Variable ambito módulo(uno): " + uno ); System.out.println("FX= Variable ambito global(dos): " + globals.dos ); } static void fx2(int dos) { System.out.println("FX2= parametro(variable uno tipo módulo; uno): " + dos ); System.out.println("FX2= valor de variable tipo módulo(uno): " + uno ); } }

modglobal2.4gl modglobal2.java

class globals{ static double cuatro; static String cinco; static int dos; static int uno; static int tres; }

globals.java

Page 69: IfxToJava2

69

La sección de memoria global es la misma para todos los módulos. Esto quiere decir que si diferentes módulos hacen referencia a una variable X todos estarán accediendo a la misma instancia de X.

Si un módulo no utiliza la sentencia GLOBALS no podrá acceder al área de memoria global aunque otro módulo del mismo programa si tenga acceso.

Debido a que el área de memoria al que se accede desde cada uno de los módulos ha de ser la misma no se puede seguir el criterio de generación de ficheros de variables globales indicado anteriormente, el cual es valido para programas monomódulo, ya que dos ficheros diferentes en JAVA harán referencia a variables diferentes. La solución consiste en utilizar un único módulo que contenga las variables globales y este será el mismo que se utiliza para guardar las variables globales creadas durante el proceso de traducción: ASGglobal_<nombremódulo>

database datos globals define dos, tres integer, cuatro decimal(2,0) define cinco char(20) end globals define uno smallint main define uno smallint let uno = 1 let dos = 2 let tres= 3 message "En main: " , uno message "En main: " , dos message "En main: " , tres call fx(uno) call fx2(uno) message "En main tras vuelta funcion: " , uno message "En main tras vuelta funcion: " , dos message "En main tras vuelta funcion: " , tres end main function fx(dos) define dos smallint, tres integer let uno = 2 let tres = uno + dos; display "En funcion fx: " ,uno display "Parametro recibido fx: ",dos end functionend function

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class multi12 { static int uno ; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGglobal_multi12.ASGcondb = new AccesDB("datos"); ASGglobal_multi12.ASGcondb.HayTransac(); int uno ; uno = 0; uno = 1 ; ASGglobal_multi12.dos = 2 ; ASGglobal_multi12.tres = 3 ; System.out.println("En main: " + uno ); System.out.println("En main: " + ASGglobal_multi12.dos ); System.out.println("En main: " + ASGglobal_multi12.tres ); fx ( uno ) ; multi22.fx2 ( uno ) ; System.out.println("En main tras vuelta funcion: " + uno ); System.out.println("En main tras vuelta funcion: " + ASGglobal_multi12.dos ); System.out.println("En main tras vuelta funcion: " + ASGglobal_multi12.tres ); } static void fx(int dos) { int tres; uno = 2 ; tres = uno + dos ; System.out.println("En funcion fx: " + uno ); System.out.println("Parametro recibido fx: " + dos ); } }

multi12.4gl multi12.java

Page 70: IfxToJava2

70

Cuadro 9: Programa multimódulo completo con sección globals

SENTENCIAS DE MANEJO DE FUNCIONES

Las sentencias de manejo de funciones son:

Sentencias de definición de función.

multi1= multi2.4gl multi3.4gl exe:multi1 multi12= multi22.4gl multi32.4gl exe:multi12

import ASGdb.*; class ASGglobal_multi12{ static AccesDB ASGcondb = null; static int dos; static int tres; static int uno; static int seis; static double cuatro; static String cinco; }

ASGmakefile ASGglobal_multi12.java

function fx3(tres) define tres smallint define tresbis integer let tresbis = 3; display "En funcion fx3: " ,tresbis display "Parametro recibido fx3: ",tres return tresbis end function

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class multi32 { static int fx3(int tres) { int tresbis ; tresbis = 3 ; System.out.println("En funcion fx3: " + tresbis ); System.out.println("Parametro recibido fx3: " + tres ); return tresbis ; } }

multi32.4gl multi32.java

globals "globals.4gl" function fx2(dos) define dos, bis smallint, bix2 char(20), tres, cuatro char(20) , cinco decimal(2,0) define dosbis integer let seis = 3 + fx3(dos); display "En funcion fx2: " , seis display "Parametro recibido fx2: ",dos end function

multi22.4gl

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class multi22 { static void fx2(int dos) { int bis; String bix2; String tres; String cuatro; double cinco; int dosbis ; ASGglobal_multi12.seis = 3 + multi32.fx3 ( dos ) ; System.out.println("En funcion fx2: " + ASGglobal_multi12.seis ); System.out.println("Parametro recibido fx2: " + dos ); } }

multi22.java

Page 71: IfxToJava2

71

Sentencia de llamada a función. Dentro de estas hay dos métodos de realizar la llamada:

Sentencia CALL

Dentro de una sentencia o expresión (LET, etc.)

SENTENCIA DE DEFINICIÓN DE FUNCIONES

Esta sentencia tiene la siguiente estructura en Informix-4GL:

FUNCTION <nombre_funcion> (<parámetros>) DECLARACION DE ARGUMENTOS DECLARACION DE VARIABLES DE LA FUNCION <SENTENCIAS> END FUNCTION

Donde, cabe destacar:

La lista de argumentos solo contiene el nombre de estos.

Los el tipo de datos de los argumentos se definen dentro del cuerpo de la función, como primera sentencia de la misma, utilizando la sentencia DEFINE.

La función puede retornar más de un valor utilizando para ello la sentencia RETURN.

Este código se transformará en una sentencia JAVA como la que sigue:

private static <valor_retorno> <nombre_fundion> (<parámetros_con_tipo> ) {

<DECLARACION DE VARIABLES DE LA FUNCION> <SENTENCIAS>

}

La principal diferencia con el código original es el hecho de que para JAVA los parámetros de las funciones se definen como: tipo identificador a diferencia de Informix-4GL que es una lista de identificadores y dentro del código de la función ha de haber una sentencia DEFINE para declarar los parámetros de la misma. Para poder generar el código de la definición de la función en JAVA será, por tanto, preciso procesar el código fuente hasta la sentencia DEFINE previamente por parte del analizador sintáctico.

Otro tema a considerar es como definir los métodos en JAVA: static o tipo class. En este punto se podría hacer mucha discusiones filosóficas sobre las ventaja o inconvenientes de cada forma, pero por: sencillez, semejanza con respecto al código original, y para evitar problemas con el código generado, como en el caso de intentar acceder desde un método estático a otro que no lo es (Ej.: main), se utilizarán métodos estáticos.

En el siguiente cuadro se muestra un ejemplo:

Page 72: IfxToJava2

72

Cuadro 10: Ejemplo de definición de funciones

En caso de que la función retorne algún valor la última instrucción de la definición de la misma será la sentencia RETURN la cual tiene una traducción directa a JAVA. Un problema que se encuentra al traducir la sentencia FUNCTION es que en caso de que esta devuelva un valor no se sabrá el tipo de dato hasta procesar la sentencia RETURN del código fuente y este ya se debe pasar en la definición de la misma al generar el código objeto.

static int funcion (�

Para solventar esta situación se ha de aplicar semántica, que nos permita determinar el valor de retorno y, por otro lado, aprovechar las características del diseño del generador de código las cuales nos permiten almacenar sentencias en bufferes intermedios antes de pasarlas al fichero objeto final. Así una función con valores de retorno será procesada como sigue:

Paso1: Inicializar buffer y elegir el primero

Paso2: Almacenar en buffer = <nombre_de_funcion>

Paso3: Pasar al buffer siguiente y almacenar = <argumentos>

Paso4: Coger el siguiente buffer y guardar en él = <sentencias>

Paso5: Procesar sentencia RETURN: almacenar el tipo de valor de retorno y guardar en buffer el identificador del valor a devolver.

Paso6: Pasar la información de los bufferes al fichero que mantiene el código objeto, para ello:

Se envía a fichero, tomando la información del buffer1, buffer2 y el tipo de retorno:

private static <tipo_retorno> <nombre_funcion> (<argumentos_con_tipo>) {

database datos define uno smallint main define uno smallint let uno = 1 message "En main: " , uno call fx(uno) message "En main tras vuelta funcion: " , uno end main function fx(dos) define dos smallint, tres integer let tres = uno + dos; display "En funcion fx: " ,uno display "Parametro recibido fx: ",dos end function

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class funcion1 { private static AccesDB ASGdb = null; static short uno ; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGdb = new AccesDB("datos"); ASGdb.HayTransac(); short uno ; uno = 0; uno = 1 ; System.out.println("En main: " + uno ); fx ( uno ) ; System.out.println("En main tras vuelta funcion: " + uno ); } static void fx(short dos) { int tres; tres = uno + dos ; System.out.println("En funcion fx: " + uno ); System.out.println("Parametro recibido fx: " + dos ); } }

funcion1.4gl funcion1.java

Page 73: IfxToJava2

73

Se envían a fichero las sentencias que forman el cuerpo e la función, incluida la sentencia RETURN

Se envía a fichero la llave de cierre de función.

En el siguiente cuadro de código se muestra un ejemplo de llamada a función desde una expresión y con valores de retorno de la misma.

Cuadro 11: Ejemplo de función con valores de retorno

Si se esta procesando un programa multimódulo la llamada a las funciones definidas en otro módulo se realizará:

NombreMódulo.metodo ( ...)

SENTENCIAS DE LLAMADA A FUCION

Una función puede ser llamada utilizando la sentencia CALL o bien formando parte de una expresión.

Esquemáticamente la sentencia CALL es:

CALL <nombre_funcion> ( <lista_id_parametros>) [ RETURNING <lista_id> ]

Y se transformará en una sentencia JAVA con la siguiente estructura:

[<metodo> . ] <nombre_funcion> (<lista_parametros> )

Un ejemplo del uso de esta sentencia se puede ver en el cuadro anterior: Ejemplo de definición de funciones.

Si la llamada a función se encuentra embebida en una expresión la sintaxis original es:

define uno smallint main define uno smallint let uno = 1 message "En main: " , uno let uno = fx1(uno) message "valor devuelte por funcion fx2: " , uno end main function fx1(dos) define dos smallint, tres integer let tres = uno + dos; display "En funcion fx: " ,uno display "Parametro recibido fx: ",dos return tres end function

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class funcion2 { private static AccesDB ASGdb = null; static int uno ; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGdb = new AccesDB("datos"); ASGdb.HayTransac(); int uno ; uno = 0; uno = 1 ; System.out.println("En main: " + uno ); uno = fx1 ( uno ) ; System.out.println("valor devuelte por funcion fx2: " + uno ); } static int fx1(int dos) { int tres; tres = uno + dos ; System.out.println("En funcion fx: " + uno ); System.out.println("Parametro recibido fx: " + dos ); return tres ; } }

funcion2.4gl funcion2.java

Page 74: IfxToJava2

74

<nombre_funcion> ( <lista_id_parametros>)

Y se transformará en una sentencia JAVA con la siguiente estructura:

[<metodo> . ] <nombre_funcion> (<lista_parametros> )

Como se ve la transformación en código JAVA será la misma. La utilización de estas dos formas de llamada a función se ejemplifica en los cuadros anteriores.

Dentro del manejo de funciones se ha limitado, la operativa del traductor, a permitir retornar solo un valor simple.

SENTENCIAS DE CONTROL DEL FLUJO

Como cualquier lenguaje de programación procedural Informix-4GL contempla un grupo de sentencias de control de flujo de programa. Las sentencias definidas por Informix-4GL son: case, continue, exit, for, foreach, if-else, y while.

SENTENCIA CASE

La sentencia CASE permite especificar bloques de código que son ejecutados condicionalmente, dependiendo del valor de una expresión. A diferencia de la sentencia IF, la sentencia CASE no limita el flujo lógico del programa a sólo dos opciones.

Esta sentencia tiene dos variantes:

Criterio de selección simple. Sí la cláusula: CASE (expresión) precede el primer bloque WHEN. Una expresión: INTEGER, SMALLINT, DECIMAL, CHAR(1), o VARCHAR(1) debe de seguir cada palabra WHEN. Si la expresión del WHEN casa con el valor de la expresión del CASE se ejecuta el bloque de sentencias y se sale de la sentencia CASE. Esquemáticamente:

case ( expresion) when <expresion1> <sentencias>

when <expresion2> <sentencias> � otherwise <sentencias_default> end case

Criterio de selección múltiple. En caso de que ninguna expresión sigue la palabra CASE. Informix-4GL trata las expresiones de cada bloque WHEN como expresiones booleanas. Si una expresión del WHEN es evaluada como TRUE se ejecuta el bloque de sentencias correspondiente. Si más de una cláusula WHEN satisface la condición sólo la primera provoca se ejecute el bloque de sentencias asociado a la misma.

case when <condicion_bool1> <sentencias>

when <condicion_bool2> <sentencias> � otherwise <sentencias_default> end case

La traducción de la sentencia CASE a JAVA se hará de forma diferente en función del criterio de selección utilizado en la sentencia CASE.

La forma de traducir la sentencia de CASE cuando se usa el criterio de selección simple será utilizando la sentencia SWITCH de JAVA, como se ejemplifica a continuación:

switch ( expresion) {

case <expresion1> : <sentencias> break; case <expresion2> : <sentencias> break; � otherwise : <sentencias_default> break; }

Page 75: IfxToJava2

75

Si la sentencia CASE original utiliza el criterio de selección múltiple la traducción a JAVA se realiza utilizando sentencias IF-ELSE encadenadas como se ejemplifica a continuación:

if ( condicion_bool1) {

<sentencias> } else if ( condicion_bool2)

{ <sentencias>

} else {

[ <sentencias_default> ] }

SENTENCIA CONTINUE

Esta sentencia transfiere el control de ejecución a la siguiente sentencia al grupo de sentencias que constituyen el bloque. Esta sentencia puede utilizarse dentro de las sentencias: CONSTRUCT, FOR, FOREACH, INPUT, MENU, y WHILE. Su sintaxis es:

continue [ construct | for | foreach | input | menu | while ]

La traducción a JAVA, para el caso de las sentencias: FOR, FOREACH, y WHILE es directa solo será necesario eliminar la palabra reservada que va detrás del CONTINUE, quedando:

continue;

En caso de que se este tratando una sentencia menú la sentencia CONTINUE significa que desde el punto en que aparece hasta el final del grupo de sentencias que se ejecutan, cuando se selecciona la opción de menú, son ignoradas. A la hora de traducir este caso se ignorarán dichas sentencias. Ejemplo:

Código fuente:

command "Continue menu" "Ejemplo de continue menu" clear screen display "Ejemplo continue menu" continue menu call ejemplowhile()

Código objeto:

ASGmenu.add("Continue menu" , "Ejemplo de continue menu" ); ASGmenu.getItem("Continue menu").addActionListener( new ActionListener () { public void actionPerformed(ActionEvent e) {

ASGarea.setText(""); ASGarea.append("Ejemplo continue menu" +"\n"); } } );

Aunque aún no se haya explicado el tratamiento de la sentencia menú observando el ejemplo se puede ver que no se ha traducido la sentencia que aparece justo detrás del CONTINUE en el código fuente.

SENTENCIA EXIT

Esta sentencia transfiere el control del flujo del programa fuera de bloque de programa actual o del propio programa.

Page 76: IfxToJava2

76

Esta sentencia tiene dos posibles variantes y cada una de ellas trae consigo una traducción diferente.

Finalización del programa actual.

exit program [ <codigo_salida> ] System.exit (<codigo_salida>);

exit main System.exit (0);

exit menu System.exit (0);

Finalización del bloque de programa actual. Sintaxis original:

exit [ case | construct | display | for | foreach | input | report | while ]

Traducción: break;

SENTENCIA FOR

Permite ejecutar un bloque de sentencias de programa un número de veces. La sintaxis original es:

for <contador> = <valor_incial> to <valor_final> [step <inc>] <sentencias> end for

Para traducir esta sentencia a JAVA se utiliza la sentencia FOR definida por JAVA adaptando para ello la sentencia original a la sintaxis de JAVA, la cual es:

for ( <contador> = <valor_inicial> ; <contador> <= <valor_vinal> ; contador += <inc> ) { <sentencias> }

Se ha de tener en cuenta a la hora de traducir esta sentencia:

Si la cláusula STEP se omite se entiende que el valor de incremento es 1.

En caso de que el valor de <inc> sea negativo se tratara de un contador descendente con lo que el operador de comparación será >= en lugar de <=.

SENTENCIA FOREACH

Esta sentencia de control de flujo de programa no es propia de un lenguaje procedimental, es añadida por Informix-4GL y tienen el objetivo de recorrer todos los elementos de un cursor.

Esquemáticamente la sintaxis de esta sentencia es:

foreach c1 into <lista_de_variables> <sentencias>

end foreach

Donde c1 es un cursor creado a través de la sentencia: DECLARE CURSOR, tal como:

declare c1 cursor for select * from tabla

La forma de traducir esta sentencia es utilizando la sentencia WHILE de JAVA que permite aportar el mismo significado que la sentencia original: recorrer todas las filas resultado de una consulta a la base de datos. De forma genérica el código generado será:

while ( ASG_rsp_c1.next() ) try { <sentencias de recuperacion de lista_de_variables> <sentencias> } catch (SQLException e) {}

Page 77: IfxToJava2

77

ASG_rsp_c1.close();

Donde ASG_rsp_c1 es una variable tipo ResultSet declarada de la siguiente forma:

ResultSet ASG_rsp_c1 = ASG_sp_c1.executeQuery("select * from tabla");

La lista de variables que aparece en la sentencia original de Informix-4GL se procesa dentro de la sentencia WHILE del código JAVA, justo al principio de la misma, y estará formada por sentencias del tipo:

vble1 = ASG_rsp_c1.getXXX(1); vble2 = ASG_rsp_c1.getXXX(2); � vbleN = ASG_rsp_c1.getXXX(N);

El número de sentencias dependerá del número de elementos de la lista de variables que constituyen la sentencia original. El tipo de método de recuperación de datos dependerá del tipo de variable en la que se espera recepcionar dicho dato.

SENTENCIA IF-ELSE

Está sentencia permite ejecutar un grupo u otro de sentencias de forma condicional. La sintaxis de Informix-4GL es muy similar a la de JAVA lo que facilita su traducción. De forma esquemática es:

if <expresión_boolena> then <sentencias> else <sentencias> end if

De forma general la traducción a JAVA será:

if ( <expresión_booleana> ) { <sentencias> } else { <sentencias> }

SENTENCIA WHILE

Esta sentencia permite ejecutar un bloque de sentencias mientras la condición, especificada a través de una expresión booleana, se cumpla. De forma esquemática su sintaxis es:

while <expresión_boolena> <sentencias> end while

La traducción a JAVA se hará pasando la estructura anterior a la propia del lenguaje, que es:

while (<expresión_boolena> ) {

<sentencias> }

A continuación se muestra un ejemplo de la utilización de todas las sentencias de control de flujo a excepción de la sentencia FOREACH el cual se muestra dentro del tratamiento de las sentencias SQL en el apartado: Sentencias de control de flujo.

Page 78: IfxToJava2

78

main define opc integer while true display "Opciones: " display "1.- Ejemplo for" display "2.- Ejemplo for con CONTINUE y EXIT" display "3.- Ejemplo while" display "Opcion: " input by name opc case opc when 1 display "Ejemplo de sentencia for" call ejemplofor() when 2 display "Ejemplo de sentencia for con CONTINUE y EXIT" call ejemploforc() when 3 display "Ejemplo de sentencia while" call ejemplowhile() otherwise display "Fin de programa" exit program end case end while end main function ejemplofor () define i integer for i = 0 to 100 display "número iteracion: ",i end for for i = 100 to 0 step -1 display "número iteracion: ",i end for end function function ejemploforc () define i integer display "CONTINUE en 10, EXIT en 20" for i = 0 to 100 if i = 10 then continue for else if i = 20 then exit for end if end if display "número iteracion: ",i end for for i = 100 to 0 step -1 if i = 80 then exit for end if if i = 90 then continue for end if display "número iteracion: ",i end for end function

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class sentctrlflujo { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int opc ; opc = 0; while ( true ) { System.out.println("Opciones: " ); System.out.println("1.- Ejemplo for" ); System.out.println("2.- Ejemplo for con CONTINUE y EXIT" ); System.out.println("3.- Ejemplo while" ); System.out.println("Opcion: " ); opc = System.in.read() -48; System.in.read(); System.in.read(); switch ( opc ) {

case 1 : System.out.println("Ejemplo de sentencia for" ); ejemplofor ( ) ; break; case 2 : System.out.println("Ejemplo de sentencia for con CONTINUE y EXIT" ); ejemploforc ( ) ; break; case 3 : System.out.println("Ejemplo de sentencia while" ); ejemplowhile ( ) ; break; default : System.out.println("Fin de programa" ); System.exit(0); break; } } } static void ejemplofor() { int i ; for(i = 0 ;i <= 100 ;i += 1) { System.out.println("número iteracion: " + i ); } for(i = 100 ;i >= 0 ;i += - 1 ) { System.out.println("número iteracion: " + i ); } }

sentctrlflujo.4gl sentctrlflujo.java

Page 79: IfxToJava2

79

Cuadro 12: Sentencias de control de flujo

SENTENCIA DE DEFINICIÓN DE MENÚS

Una sentencia MENU proporciona una estructura en la cual situar sentencias que realizan acciones descritas a través del nombre de la opción de menú. Esquemáticamente una sentencia menú se define en Informix-4GL como:

Menu �nombre menu� Command �opción de menu� [ �ayuda opción de menu�] <sentencias> � [continue menu]

function ejemplowhile() define i integer let i = 0 while true let i = i + 1 if i == 10 then continue while end if display "Valor de interacion: ", i if i == 20 then exit while end if end while end function

static void ejemploforc() { int i ; System.out.println("CONTINUE en 10+ EXIT en 20" ); for(i = 0 ;i <= 100 ;i += 1) { if ( i == 10 ) { continue; } else { if ( i == 20 ) { break; } } System.out.println("número iteracion: " + i ); } for(i = 100 ;i >= 0 ;i += - 1 ) { if ( i == 80 ) { break; } if ( i == 90 ) { continue; } System.out.println("número iteracion: " + i ); } } static void ejemplowhile() { int i ; i = 0 ; while ( true ) { i = i + 1 ; if ( i == 10 ) { continue; } System.out.println("Valor de interacion: " + i ); if ( i == 20 ) { break; } }

Page 80: IfxToJava2

80

� [next option �opción de menu�] � [exit menu] � Command �opción de menu� [�ayuda opción de mnu�] <sentencias> � End menu

Esta sentencia se traduce a JAVA como la creación de un menú al estilo Windows y con tantos submenús, que aparecen al desplegarlo, como cláusulas COMMAND aparecen en el cuerpo de la sentencia.

Todas las sentencias que aparecen dentro del cuerpo de cada opción de menú, COMMAND, se colocarán, a la hora de generar código objeto, en el cuerpo del listener asociado al elemento de menú creado. Así por cada sentencia COMMAND como la que sigue:

command "Ejemplo1" "Ejemplo sentencia for" clear screen display "Ejemplo de sentencia for" call ejemplofor()

Se transforma en un sentencia JAVA tal como:

<JMenuItem>.add("Ejemplo1" , "Ejemplo sentencia for" ); <JMenuItem>.addActionListener( new ActionListener () { public void actionPerformed(ActionEvent e) { ASGarea.setText(""); ASGarea.append("Ejemplo de sentencia for" +"\n"); ejemplofor ( ) ; } } );

Como se muestra en el caso anterior por cada opción de menú de Informix-4GL se crea una Item de menú JAVA y se añade un listener a éste.

Dentro de las sentencias que pueden ir asociada a cada opción de menú hay destacar:

Continue menu. Se encarga de saltar la ejecución que hay desde el punto en que aparece hasta el final de la opción de menú. Ej.:

command "Continue menu" "Ejemplo de continue menu" clear screen display "Ejemplo continue menu" continue menu call ejemplowhile()

En este caso la llamada a la función ejemplowhile() no se producirá.

La traducción lógica a JAVA del comando CONTINUE MENU sería con la sentencia RETURN, pero esto produciría un error al compilar el programa JAVA ya que la llamada a la función no es alcanzada. Para evitar este error de compilación lo que se hará será omitir la traducción de toda sentencia que haya a continuación del CONTINUE MENU omitiendo la generación de código objeto asociado a las mismas.

Exit menu. Finaliza la ejecución del menú y por consiguiente del programa. La traducción a JAVA será utilizando la sentencia: Sytem.exit(0);

Page 81: IfxToJava2

81

Next option. Esta subsentencia del MENU permite indicar que opción del menú quedará seleccionada después de ejecutar esta. En el estilo Windows de menús no tiene sentido la traducción de esta opción.

Esta sentencia solo es procesada si se está generando código objeto para un entorno gráfico.

A continuación se muestra un ejemplo de un programa conteniendo la sentencia menú:

main define opc integer menu "Opciones" command "Ejemplo1" "Ejemplo sentencia for" clear screen display "Ejemplo de sentencia for" call ejemplofor() command key(J) "eJemplo2" "Ejemplo for con CONTINUE y EXIT" clear screen display "Ejemplo de sentencia for con CONTINUE y EXIT" call ejemploforc() command key(W) "ejemplo While" "Ejemplo de sentencia While" clear screen display "Ejemplo de sentencia while" call ejemplowhile() command "Continue menu" "Ejemplo de continue menu" clear screen display "Ejemplo continue menu" continue menu call ejemplowhile() command "Salir" "Abandonar el programa" exit menu end menu

import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; import javax.swing.*; import java.awt.*; import ASGgrafico.*; import java.awt.event.*; public class sentmenu extends JApplet { private static AccesDB ASGcondb = null; private static JTextArea ASGarea = new JTextArea(33,70); static ASGMenu ASGmenu; public static void main(String argv[]) throws Exception { Console.run(new sentmenu(),800,600); } public void init() { Container ASGcp = getContentPane(); ASGcp.setLayout(new FlowLayout()); ASGarea.setEditable(false); ASGcp.add(new JScrollPane(ASGarea)); ASGarea.setText(""); try{ ASGmain(); } catch (Exception e ) {} } public void ASGmain () throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int opc ; opc = 0; ASGmenu = new ASGMenu("Opciones" ); ASGmenu.add("Ejemplo1" , "Ejemplo sentencia for" );

sentmenu.4gl sentmenu.java

Page 82: IfxToJava2

82

Cuadro 13: Ejemplo sentencias menú

ASGmenu.getItem("Ejemplo1").addActionListener( new ActionListener () { public void actionPerformed(ActionEvent e) { ASGarea.setText(""); ASGarea.append("Ejemplo de sentencia for" +"\n"); ejemplofor ( ) ; } } ); ASGmenu.add('j' , "eJemplo2" , "Ejemplo for con CONTINUE y EXIT" ); ASGmenu.getItem("eJemplo2").addActionListener( new ActionListener () { public void actionPerformed(ActionEvent e) { ASGarea.setText(""); ASGarea.append("Ejemplo de sentencia for con CONTINUE y EXIT" +"\n") ; ejemploforc ( ) ; } } ); ASGmenu.add('w' , "ejemplo While" , "Ejemplo de sentencia While" ); ASGmenu.getItem("ejemplo While").addActionListener( new ActionListener () { public void actionPerformed(ActionEvent e) { ASGarea.setText(""); ASGarea.append("Ejemplo de sentencia while" +"\n"); ejemplowhile ( ) ; } } ); ASGmenu.add("Continue menu" , "Ejemplo de continue menu" ); ASGmenu.getItem("Continue menu").addActionListener( new ActionListener () { public void actionPerformed(ActionEvent e) { ASGarea.setText(""); ASGarea.append("Ejemplo continue menu" +"\n"); } } ); ASGmenu.add("Salir" , "Abandonar el programa" ); ASGmenu.getItem("Salir").addActionListener( new ActionListener () { public void actionPerformed(ActionEvent e) { System.exit(0); } } ); setJMenuBar(ASGmenu.get()); } �

sentmenu.java (2)

Page 83: IfxToJava2

83

El programa resultante de la ejecución de los ejemplos anteriores tanto él fuente de Informix-4GL como él objeto en JAVA se muestra en las siguientes figuras:

Figura 11: Resultado de ejecución de un programa con menú en Informix

Figura 12: Resultado de ejecución de un programa con menú en Java

SENTENCIAS DE DECLARACIÓN Y UTILIZACIÓN DE VARIABLES

La sentencia de declaración de variables que proporciona Informix-4GL es DEFINE, la cual tiene la siguiente estructura:

define <lista de identificadores> <tipo de dato> [ , <lista de identificadores> <tipo de dato> ] [, .. n]

Dentro de una sentencia DEFINE se pueden declarar más de una variable y de más de un tipo de datos.

En un bloque de declaración de variables puede haber más de una sentencia DEFINE. Dentro de un programa Informix-4GL se puede declarar variables en tres puntos:

Page 84: IfxToJava2

84

Al principio del mismo dentro del bloque GLOBALS.

Después de la sentencia GLOBALS y antes del bloque MAIN.

Dentro de los bloques de programa: MAIN, FUNCTION y REPORT justo al principio de los mismos antes de cualquier otra sentencia de programa.

JAVA es mucho más libre en cuanto los puntos de programa en los cuales se pueden definir variables, esto aporta sencillez en este aspecto de la traducción. Esquemáticamente su sintaxis es:

<tipo de dato> <lista de identificadores> ;

La traducción de esta sentencia tiene varias peculiaridades:

Por cada tupla <lista de identificadores> <tipo de dato> de la sentencia original se genera una sentencia (línea) distinta de código objeto. Ejemplo:

Código fuente:

define uno, dos, tres integer, cuatro cinco char(1)

define seis, siete double

Código objeto:

integer uno, dos, tres; String cuatro, cinco; double seis, siete;

En la sentencia objeto el tipo de dato se sitúa antes de los identificadores, esto se puede implementar gracias a las características del generador de código que permite almacenar en bufferes intermedios partes de la sentencia a generar y luego procesar estos. En este caso se tendrá en un buffer el tipo de dato y otro las variables a definir y se mandaran al fichero objeto en el orden adecuado.

Otro tema a considerar es el tipo de dato JAVA a utilizar en función del tipo de dato Informix-4GL del código fuente. Para ello se utiliza la siguiente tabla:

Tipo de dato Informix-4GL Tipo de dato Java

CHAR, CHARACTER String

VARCHAR String

TEXT String

NUMERIC | DECIMAL | DEC java.math.BigDecimal | double

SMALLINT short

INTEGER | INT int

REAL | SMALLFLOAT float

FLOAT | DOUBLE double

BYTE byte[]

DATE java.sql.Date

TIMESTAMP java.sql.Timestamp

Tabla 8: Mapeo entre tipos de datos Informix-4GL y JAVA

Page 85: IfxToJava2

85

UTILIZACIÓN DE VARIABLES

Informix-4GL recomienda la inicialización de las variables antes de su uso aunque no obliga a ello. JAVA por el contrario si obliga a inicializar las variables antes de su utilización.

Dentro del proceso de traducción y justo a continuación de las sentencias de declaración de variables se añadirá un código para la inicialización de las mismas evitando así problemas a la hora de compilar el programa JAVA generado. El criterio que se seguirá, para inicializar variables en función del tipo de dato, se muestra en la siguiente tabla:

Tipo de dato JAVA Valor inicial

String �� (espacio en blanco)

Short, int 0

Flota, double 0,0

Date, Timestamp null

Byte null

Bigdecimal null

Tabla 9: Valor de inicialización de variables

Para la asignación de valores a una variable Informix-4GL utiliza la sentencia LET con la siguiente sintaxis:

let variable = <expresión>

La traducción a JAVA es directa, en principio, es suficiente con quitar el token LET. El problema que puede plantear es la compatibilidad entre el tipo de valor a asignar y la variable, por ejemplo: si queremos asignar la constante today a la una variable tipo java.sql.date habrá que hacer una procesamiento de la constante today ya que JAVA no la reconoce. Este problema se plantea básicamente con el tipo de dato DATE y DATETIME de Informix-4GL y se soluciona durante el proceso de traducción realizando la conversión adecuada.

La solución planteada para hacer estas asignaciones es definir métodos auxiliares que se puedan lanzar en tiempo de ejecución y se encarguen de pasar el formato Informix-4GL a JAVA. Se debe tener en cuenta que JAVA, a diferencia de Informix, interpreta las fechas como el número de milisegundos desde el 1 de enero de 1970. En las siguientes tablas se muestra la traducción de las expresiones de Informix-4GL a JAVA utilizadas, al menos, en la sentencia LET:

Informix-4GL Conversión a JAVA

today new Date(new java.util.Date().getTime()) ;

�22/07/2007� ASGfaux.fecha("22/07/2007") ;

4000 ASGfaux.cteIntToFechaJ(40000) ;

date (<fecha> ) ASGfaux.fecha ( <fecha> ) ;

mdy (<mes>, <dia>, <año> ) ASGfaux.mdy (<mes>, <dia>, <año> ) ;

Tabla 10: Asigación de expresiones tipo fecha

Informix-4GL Conversión a JAVA

current new Timestamp(new java.util.Date().getTime()) ;

�2007-07-22 12:33:20.444� ASGfaux.fechahora("2007-07-22 12:33:20.444") ;

Page 86: IfxToJava2

86

datetime (2007-07-22 12:33:20.444) year to fraction

ASGfaux.fechahora("2007-07-22 12:33:20.444") ;

Tabla 11: Asignación de expresiones tipo fecha/hora

Informix-4GL Conversión a JAVA

day( <fecha> ) ASGfaux.day( <fecha> ) ;

moth ( <fecha> ) ASGfaux.month ( <fecha> ) ;

year ( <fecha> ) ASGfaux.year ( <fecha> ) ;

weekday ( <fecha> ) ASGfaux.dayweek ( <fecha> ) ;

Tabla 12: Asignación de expresiones tipo fecha a entero

Todas estas funciones están definidas en el paquete ASGutil el cual es importado en todos los programas generados.

ÁMBITO DE VARIABLES Como se explicó en el punto: Características básicas del Lenguaje dentro del apartado: Estudio del lenguaje Informix-4GL éste maneja tres tipos de variables: globales, de módulo y locales y cada una con su ámbito. En este apartado se presentará la forma de afrontar el problema durante el proceso de traducción de tal forma que mantenga los mismos ámbitos de variables y con la misma visibilidad en el código objeto.

A la hora de pasar los ámbitos a JAVA se puede pensar que no hay que tener nada en cuenta ya que se mantienen los mismos nombres de identificadores, pero si habrá que realizar un estudio detallado con objeto de mantener el mismo significado y visibilidad de los mismos como se verá a continuación:

Las variables locales, que tienen significado solo dentro del bloque (main, función o report) en el cual son declaradas, no plantean ningún problema. Al pasar esta variables a JAVA se definirán dentro del método correspondiente (main, función) y el propio JAVA garantiza que tengan la misma visibilidad que en el programa original.

Las variables tipo módulo, que tienen significado en todos los bloques de programa que están localizados en el mismos fichero fuente, no plantean ningún problema siempre y cuando se definan el punto adecuado dentro del programa JAVA. En Informix-4GL se definen al principio del módulo (antes de el bloque de programa main), y en JAVA se declararán dentro de la clase principal y fuera de cualquier método y antes de la aparición de ninguno de ellos así se garantizará que sean visibles a toda la clase.

Las variables globales son visibles y mantienen su valor en cualquier parte de los programas multimódulo. Esta característica implica que la traducción a JAVA no es tan directa como en los casos anteriores.

En Informix-4Gl las variables globales son declaradas en la sección GLOBALS la cual debe de aparecer al principio de cada módulo que desee utilizarlas. Una vez declaradas son accesibles desde cualquier módulo y mantienen su valor.

La forma de implementar este tipo de variables en JAVA es definiéndolas en un módulo independiente, de tal forma que puedan ser referenciadas desde cualquiera de los módulos que conforman el programa, y de tipo estático, garantizando así la persistencia de su valor.

El acceso a este tipo de variable, en los programas JAVA, será diferente a como se realiza en el código fuente debido a que se ha de especificar como prefijo el nombre del módulo en el cual están declaradas: <módulo>.<variable>

Page 87: IfxToJava2

87

Hasta ahora queda claro que las variables locales y de tipo módulo según se traducen a JAVA mantienen su sintaxis y visibilidad, pero no ocurre lo mismo con las variables globales. Como las variables globales son referenciadas con un prefijo se ha de saber, en tiempo de traducción, cuando se esta haciendo referencia a una de ellas para así colocar éste. La forma de poder saber si se ha de generar la variable con prefijo es a través de la utilización de la tabla de símbolos durante el proceso de traducción, de tal forma que si se determina que la variable es de tipo global lo llevará y en caso contrario no.

En este punto es donde mayor se demuestra la necesidad de la tabla de símbolos durante el proceso de traducción. La tabla de símbolos utilizada guarda 4 valores: identificador, tipo, ámbito y módulo. A continuación se muestra un ejemplo:

cinco$1 6 1 ASGglobals_modglobal cuatro$1 2 1 ASGglobals_modglobal uno$2 3 2 modglobal dos$3 3 3 modglobal uno$1 3 1 ASGglobals_modglobal tres$1 3 1 ASGglobals_modglobal dos$1 3 1 ASGglobals_modglobal fx$2 15 2 modglobal fx2$2 15 2 modglobal

Con esta definición y las características de funcionamiento que se le han definido al tratar una variable en un módulo se podrá determinar si es de tipo: local, módulo, o global.

En la sección: Sentencias de definición del módulo principal de programa, a la hora de tratar el módulo globals se pueden ver dos casos en los que se ejemplifica la utilización del ámbito de variables. Estos casos son: Ejemplo de bloque de programa globals y Ejemplo módulo de programa globals.

Page 88: IfxToJava2

ESTUDIO DEL SQL DE INFORMIX

Page 89: IfxToJava2

89

PLANTEAMIENTO SQL El planteamiento que se realiza dentro del estudio del SQL de Informix es muy ambicioso:

Por un lado se pretende traducir todas las sentencias SQL que define Informix a sentencias JAVA que puedan ser ejecutadas, a través del Driver JDBC, sobre el gestor de bases datos.

Por otro que las sentencias SQL creadas para ser ejecutada en Informix SE, y por consiguiente específicas del mismo, puedan ser ejecutadas sobre cualquier gestor de bases de datos.

Este segundo objetivo es altamente complicado debido a que no todas las sentencias SQL definidas por Informix siguen los estándares SQL y a que existen notables diferencias entre la definición sintáctica que hace Informix de las mismas con respecto a la que hacen el resto de gestores de bases de datos.

El análisis se centra en los gestores de bases de datos destino: Informix SE, Informix OL, SqlServer, Oracle y Db2.

Dentro de esta sección no solo se estudian con total detalle todas las sentencias SQL de Informix-SQL con el objetivo de conseguir generar código objeto valido y equivalente para otros gestores sino que se llega más allá analizando:

Los tipos de datos soportados por Informix, sus equivalentes en el resto de gestores, los validos para el JDBC JAVA y las compatibilidades con los tipos de datos del lenguaje de programación.

Las conversiones entre tipos de datos.

Las operaciones sobre expresiones.

El propietario y forma de acceso a tablas.

Etc.

Como resultado de todo este estudio se conseguirán programas equivalentes a los originales y que se puedan ejecutar sobre diferentes gestores de bases de datos.

ENFOQUE Para cumplir el objetivo marcado se debe enfocar el problema desde dos puntos de vista:

El estudio de la sintaxis de las sentencias SQL de Informix y de las equivalentes en el resto de gestores de bases de datos con objeto de ver la compatibilidad de las mismas.

Se empezara estudiando las sentencias SQL que suministra Informix-SQL, si estas cumplen el estándar SQL89 serán directamente ejecutables sobre cualquiera de los otros gestores de bases de datos. Los problemas surgen en aquellas sentencias definidas por el gestor de base de datos Informix que amplían dicho estándar. En esos casos se hará un estudio detallado de las mismas para ver como, si es posible, traducirlas para que puedan ser ejecutadas en el resto de gestores de bases de datos.

Y la traducción de la sentencia a un código objeto que permita la ejecución de la misma sobre cualquier gestor de bases de datos de los aquí estudiados.

En un este punto se ha de ver como se hará la traducción de la sentencia SQL a código objeto de tal forma que se garantice que dicha sentencia se pueda lanzar contra los distintos gestores de bases de datos. JAVA ha definido un API de bajo nivel que soporta las funcionalidades SQL, llamada: API JDBC. Este API permite desarrollar aplicaciones de acceso a bases de datos de alto nivel y si se dispone del Driver adecuado para el gestor de bases de datos pueden ser ejecutadas sobre éste.

Ante toda sentencia que proporciona Informix-SQL se seguirán varias pautas:

Page 90: IfxToJava2

90

1.- Ver si el resto de gestores la interpretan de igual forma, en caso afirmativo no plantean ningún problema.

2.- En otro caso buscar soluciones alternativas, como:

Necesidad o no de traducir esas sentencias. Algunas sentencias son puras de administración y es muy raro el caso en el cual aparecen en un programa. Ante una de estas se sugerirá que el administrador las ejecute directamente sobre la herramienta de administración de la base de datos. Como Ejemplo tenemos la sentencia: drop database.

Buscar posibles variantes de la sentencia inicial en el gestor de bases de datos destino. Ejemplo: la palabra reservada constraint en Informix va detrás de la definición de las restricciones, sin embargo en SqlServer va delante.

Dividir la sentencia original en varias subsentencias de tal forma que a través de estas se pueda representar el comportamiento de la sentencia original. Ej.: sentencia alter tabla

Ver si el lenguaje de programación permite alguna posibilidad alternativa. Ejemplo: en Informix existe una sentencia database <nombre base de datos> que permite especificar la base de datos sobre la que se trabaja a partir de su aparición. Esta sentencia no es soportada por ningún otro gestor de bases de datos. Una posibilidad es entender esta sentencia como la conexión a la base de datos, con lo cual se podrá hacer una traducción a cualquier gestor utilizando las sentencias de la clase Connection de JDBC.

Buscar soluciones de implementación a través del lenguaje de programación JAVA. Ejemplo: la sentencia alter table, de Informix, permite añadir campos en cualquier posición, sin embargo el resto de gestores solo lo permiten al final. Una solución es hacer código en Java que implemente esta forma de alteración de tablas de la base de datos.

Etc.

Posteriormente se hará un estudio detallado de cada sentencia SQL y en cada caso se indicará, en función del gestor de bases de datos destino, la forma de proceder.

PRERREQUISITOS Para llevar a efecto la transformación de sentencias generadas para Informix-SQL a JAVA se limitará a utilizar las funcionalidades estándar que ofrece el API JDBC 2.0 de JAVA.

El código fuente del que se parte para realizar el estudio SQL esta escrito en la versión 4.10 de Informix y por tanto será la especificación sintáctica de la que se parta.

Las versiones mínimas de los gestores de bases de datos sobre los cuales se podrá lanza él código objeto generado son:

Informix 4.10 o superior

SqlServer 2005 o superior. Se podría plantear usar versiones inferiores (SqlServer 7 ó 2000) pero se han encontrado dos problemas que, auque salvables, la versión 2005 ya implementa,-Estos son:

Definición de Sinónimos

Distinción entre mayúsculas y minúsculas a la hora de tratar cadenas. En versiones anteriores el gestor de base de datos no diferenciaba entre mayúsculas y minúsculas a la hora de hacer comparaciones con campos tipo carácter.

Oracle versión 9i o superior. Esta es la primera versión de Oracle en la que se implementa el tipo de dato TIMESTAMP y este dato es la única causa que no permite utilizar versiones inferiores.

Db2 versión 8 o superior.

Page 91: IfxToJava2

91

ESTANDARES SQL SQL es el lenguaje para definir y manipular datos almacenados en una base de datos. Fue originalmente creado por IBM y pronto surgieron varios dialectos de SQL desarrollados por distintos proveedores. El Instituto Nacional Americano de Estándares (ANSI), en 1980, comienza a desarrollar un lenguaje estándar para bases de datos relacionales. ANSI y la Organización Internacional de Estándares (ISO) publican el estándar SQL en 1986 y 1987 respectivamente. Esta versión es conocida como SQL/86.

La versión SQL/86 fue en su mayor parte basada en el dialecto original creado por IBM. SQL/89, también conocido como SQL1, añade integridad referencial. SQL/89 consta de dos niveles: el nivel 1 es el antiguo SQL/86 y el nivel 2 consiste en el SQL/86 con reglas de integridad.

El siguiente estándar salió en 1992 y es llamado SQL/92 o SQL2 e incluye SQL embebido, catálogos y esquemas del sistema, y conversiones entre tipos. Este estándar consta de tres niveles: el nivel 1, o nivel de acceso, consiste en el SQL/89 mas algunos mensajes de error estándar, el segundo nivel, llamado nivel intermedio, define nuevas operaciones, actividades referenciales, y nuevos tipos de datos, el tercer nivel , conocido como nivel completo, añade comandos para sistemas cliente/servidor.

El ultimo nivel, es el SQL3 el cual aporta nuevas características principalmente debido a la inclusión de los conceptos de Orientación a objetos y en otros aspectos como: nuevos tipos de datos, funciones SQL, procedimientos almacenados, triggers, etc.

En la siguiente tabla se muestran todos los estándares y sus características:

Estándar Nivel Características

ANSI SQL/89 Nivel 1 Definición y manipulación de datos: selección, proyección, uniones.

SQL embebido

Cursores

Nivel 2 Reglas de integridad: cláusula CHECK, PRIMARY KEY, referencia a columnas (FOREIGN KEY)

SQL/92 Nivel de acceso Mensajes de errores estándar: SQLSTATE

Lenguajes anfitriones adicionales: C, Ada.

Nivel intermedio Tipos de datos: DATE, TIME

Operadores: OUTER JOIN, OUTER UNION, INSERT SELECT

Dominios

Estructuras de manipulación: ALTER TABLE

Dynamic SQL

Acciones referenciales: ON DELTE

Intervalos de tiempo: YEAR, MONTH, DAY, HOUR

Aritmética sobre unidades de tiempo.

SQL completo Establecer conexiones entre cliente y servidor: CONNECT TO, SET

Page 92: IfxToJava2

92

CONNECTION, DISCONNECT

Acciones referenciales: ON UPDATE

Reglas de integridad: CREATE ASSERTION... CHECK, SET CONSTRAINTS ON/OFF, FETCH PRIOR, FETCH RELATIVE

Tipos de datos: BIT y STRING HEX

SQL3 Orientación a objetos

Triggers

Procedimientos almacenados

Funciones SQL

Polimorfismo

Tipos de datos: LIST, ARRAY SET

Comandos DML recursivos: RECUSIVE UNION

Tabla 13: Estándar SQL

Los productos Informix-SQL cumplen el nivel de conformidad con el nivel ANSI SQL89 en los servidores de bases de datos Informix OL (Online) y en los servidores de bases de datos Informix SE (Standard Engine) con las siguientes excepciones:

Chequeo de restricciones.

Transacciones serializables.

Oracle 8i (y superiores) soporta completamente el nivel SQL92 básico (o de acceso) y algunas características de los niveles intermedio o completo.

SqlServer 7.0 (y superiores) es compatible con el estándar nivel básico de SQL92, y con otras muchas funciones de los niveles intermedio y completo.

DB2 Versión 7.0 también cumple al menos el nivel básico de compatibilidad SQL92.

CONVENCIONES DE SINTAXIS Durante todo este documento, a la hora especificar la sintaxis de las sentencia SQL, se seguirán una serie de convenciones que se detallan a continuación:

La sintaxis de las sentencias SQL se especifica en formato BNF extendida.

Sí en la definición sintáctica aparece algún elemento que pueda formar parte de la notación BNF extendida, este se resaltará en negrita para indicar que forma parte de la sentencia que se está definiendo.

A la hora de especificar la sintaxis de las sentencias SQL del resto de gestores de bases solo incluirá la parte necesaria que permita garantizar que la sentencia original de Informix-SQL es soportada por los mismos1.

Cuando se esta analizando una sentencia SQL para determinar si es compatible con la sentencia original, de Informix-SQL, se resaltan en color azul aquellas partes de la misma que no plantean ningún problema.

1 Para ver las sentencias completas dirigirse a la documentación indicada en la bibliografía.

Page 93: IfxToJava2

93

CLASIFICACIÓN DE LAS SENTENCIAS SQL Las sentencias de Informix-SQL se dividen en los siguientes tipos:

SENTENCIAS SQL DE DEFINICIÓN DE DATOS

Incluye el grupo de sentencias que soportan la definición o declaración de los objetos de la base de datos. En la tabla siguiente se detallan el grupo de sentencias que incluye Informix-SQL en su sintaxis:

ALTER INDEX CREATE TABLE DROP TABLE

ALTER TABLE CREATE VIEW DROP VIEW

CLOSE DATABASE DATABASE RENAME COLUMN

CREATE DATABASE DROP DATABASE RENAME TABLE

CREATE INDEX DROP INDEX

CREATE SYNONYM DROP SYNONYM

Tabla 14: Sentencias de definición de datos

SENTENCIAS SQL DE MANIPULACIÓN DE DATOS

Este grupo de sentencias permiten la manipulación de los datos de la base de datos. En la siguiente tabla se especifican estas:

INSERT LOAD UNLOAD

DELETE SELECT UPDATE

Tabla 15: Sentencias de manipulación de datos

SENTENCIAS SQL DE MANIPULACIÓN DE CURSORES

El grupo de sentencias que permiten la manipulación de datos a través de cursores, son:

CLOSE FETCH OPEN

DECLARE FLUSH PUT

Tabla 16: Sentencias de manipulación de cursores

SENTENCIAS SQL DE OPTIMIZACIÓN-INFORMACIÓN

Lo forman un grupo de sentencias que permiten optimizar los accesos a la base de datos así como obtener información para depuración. Este grupo de sentencias son muy específicas del gestor de bases de datos Informix-SQL lo cual no quiere decir que el resto de gestores aporten sus propias herramientas de optimización y depuración. Lo forman las siguientes sentencias:

SET EXPLAIN SET OPTIMIZATION UPDATE STATISTICS

Tabla 17: Sentencias de optimización-Información

SENTENCIAS SQL DE CONTROL DE ACCESO A LOS DATOS

Grupo de sentencias que permiten tratar los bloqueos y los permisos de acceso a los datos y operaciones sobre los mismos:

GRANT REVOKE SET LOCK MODE

LOCK TABLE UNLOCK TABLE

Page 94: IfxToJava2

94

Tabla 18: Sentencias de control de acceso a los datos

SENTENCIAS SQL QUE GARANTIZAN LA INTEGRIDAD DE LOS DATOS

Este grupo de sentencias se encargan de gestionar las transacciones y de auditar tablas en Informix-SQL:

BEGIN WORK COMMIT WORK CREATE AUDIT

DROP AUDIT ROLLBACK WORK START DATABASE

Tabla 19: Sentencias de integridad de los datos

SENTENCIAS SQL DE MANIPULACIÓN DINÁMICA DE DATOS

Sentencias de permitir la preparación y ejecución de sentencias SQL de forma dinámica, son:

EXECUTE FREE PREPARE

Tabla 20: Sentencias de manipulación dinámica de datos

ESTUDIO DE LAS SENTENCIAS SQL SENTENCIA ALTER INDEX

Esta sentencia permite alterar un índice de una tabla existente.

La sentencia ALTER INDEX trabaja únicamente sobre índices que han sido creados con la sentencia CREATE INDEX; esta no afecta a las restricciones (constraints) que han sido creados con la sentencia CREATE TABLE.

No se pueden alterar índices de las tablas temporales.

SINTAXIS DE INFORMIX

<ALTER NDEX> ::= ALTER INDEX nombreindice TO [NOT] CLUSTER

La opción TO CLUSTER causa que las filas en la tabla indexada sean reordenadas en el orden del índice creado.

Esta sentencia no esta contemplada por el SQL89 y tampoco por en el nivel básico del estándar SQL92, es una extensión que aporta Informix-SQL, y no es soportada en el mismo aspecto que Informix-SQL por ningún otro gestor de bases de datos de los contemplados aquí.

IMPLEMENTACION

La traducción de esta sentencia al código objeto, JAVA, es inmediata puesto que se trata de una sentencia estática, ya que el nombreindice es un identificador o una constante cadena. Lo único que habrá que hacer es lanzar la sentencia contra el gestor de bases de datos.

Dado que: la utilidad de esta sentencia no es excesiva, su uso a nivel de programas es prácticamente nulo (al ser una sentencia de administración de la base de datos), no es soportada por el estándar SQL89, y que el resto de gestores de bases de datos no la soportan será omitida la traducción de dicha sentencia a JAVA. A la hora de lanzar el proceso de traducción, si aparece esta sentencia en el código fuente, se notificará la no traducción de la misma con un mensaje como el que sigue:

Mensaje: Warning: Sentencia alter index no generada

Page 95: IfxToJava2

95

SENTENCIA ALTER TABLE

Esta sentencia modifica una definición de tabla al alterar, agregar, o quitar columnas y restricciones o al deshabilitar o habilitar restricciones. Para poder modificar una tabla se deben tener permisos de alteración sobre la misma.

Cuando una columna es añadida, la tabla existente es extendida con la nueva columna, la cual se coloca al final de la definición de la tabla2.

Cuando una columna es alterada es posible cambiar el tipo de dato de la columna que se altera. Si se cambia el tipo de dato el nuevo tipo ha de ser compatible con los datos que ya existen en la columna.

Cuando una columna es �dropada�, esta es borrada de la tabla así como las vistas, restricciones e índices que hacen referencia al campo borrado.

SINTAXIS DE INFORMIX

<ALTER TABLE> ::= ALTER TABLE nombretabla [ MODIFY ( { nombrecolumna < nuevotipotatos> [NOT NULL] {[UNIQUE | DISTINCT] [CONSTRAINT nombrerestriccion] }[,...n] }[,...n] ) | ADD ( { nombrecolumna <tipodato> [NOT NULL] {[UNIQUE | DISTINCT] [CONSTRAINT nombrerestriccion] }[,...n] [BEFORE nombrecolumna] }[,...n]) | DROP (nombrecolumna[,...n]) | ADD CONSTRAINT {[UNIQUE | DISTINCT] (nombrecolumna[,...n]) [CONSTRAINT nombrerestriccion] }[,...n] | DROP CONSTRAINT (nombrerestriccion [,...n] ) ] {,...n}

Esta sentencia no es contemplada por el estándar SQL89, Informix-SQL lo amplia al usarla, aunque si es soportada, en parte, por el estándar básico SQL92 lo cual facilitará mucho el poder usarla en otros gestores de bases de datos.

Observando esta sentencia vemos:

La opción MODIFY no esta contemplada por el estándar básico SQL92, aunque de una u otra forma la mayoría de los gestores de bases de datos lo soportan. La opción: CONSTRAINT nombrerestriccion es una aplicación que aporta Informix-SQL a la versión 4.10.

Por defecto los campos que se añadan o modifiquen pueden tomar valores nulos en caso contrario se debe de especificar con la cláusula NOT NULL. Esto cumple el estándar básico SQL92, pero en dicho estándar se considera esta cláusula como una restricción y en Informix-SQL no.

Como restricciones solo admite: UNIQUE y DISTINCT. Ambas restricciones significan lo mismo: que el campo sobre el que se aplica no admitirá valores duplicados. DISTINCT no es soportado por el estándar SQL92.

Si aparece la palabra CONSTRAINT, como restricción de una columna, Informix-SQL contempla que se debe de colocar esta detrás de la propia restricción, sin embargo el estándar SQL92 indica que a de aparecer delante y el resto de gestores de bases de datos estudiados también lo entienden así.

2 A excepción de Informix-SQL que permite posicionar la nueva columna en cualquier posición.

Page 96: IfxToJava2

96

Si aparece una cláusula de restricción de tabla el estándar SQL92 obliga en el caso de aparecer la palabra CONSTRAINT a que se le de un nombre a la restricción. Esto lo respetan la mayoría de los gestores de bases de datos, pero Informix-SQL no obliga a ello.

Al añadir columnas a una tabla ya creada Informix permite especificar en que posición se colocara el nuevo campo, usando para ello la cláusula BEFORE. Esto no es soportado por el estándar SQL92 el cual indica que todo campo se añadirá al final. La posición en la que se coloca el nuevo campo no tiene ninguna trascendencia para el funcionamiento o utilización de la tabla.

Cuando se añade o borra campos a una tabla Informix-SQL permite hacerlo sobre más de uno al mismo tiempo, en cambio el estándar básico SQL92 solo permite hacerlo sobre un campo de por cada sentencia ALTER. Todos los gestores estudiados se ajustan al estándar en esta característica.

Cuando se borran restricciones el estándar básico SQL92 solo permite hacerlo sobre una de cada vez en cambio Informix-SQL permite borrar más de una por cada sentencia. El resto de gestores estudiados se suelen ajustar al estándar.

El estándar básico SQL92 solo admite una cláusula (ADD, MODIFY, o DROP) dentro de la sentencia ALTER TABLE, Informix-SQL admite más de una separadas por comas, otros gestores lo permiten sin ningún separador, y SqlServer no lo permite.

SINTAXIS DE SQLSERVER

<ALTER TABLE> ::= ALTER TABLE nombretabla [ ALTER COLUMN nombrecolumna { <nuevotipodatos> [ NULL | NOT NULL ] | {ADD | DROP} ROWGUIDCOL } | ADD { <definicion de columna> | nombrecolumna AS <expresioncalculadacolumna> }[,...n] | [WITH CHECK | WITH NOCHECK] ADD { <restricciondetabla> }[,...n] | DROP { [CONSTRAINT] nombrerestriccion | COLUMN nombrecolumna }[,...n] | {CHECK | NOCHECK} CONSTRAINT {ALL | nombrerestriccion [,�n]} | {ENABLE | DISABLE} TRIGGER {ALL | nombredesencadenador [,�n]} ] <definicion de columna> ::= { nombrecolumna tipodatos } [ [ DEFAULT expresionconstante ] | [ IDENTITY [(inicializacion, incremento ) [NOT FOR REPLICATION] ] ] ] [ ROWGUIDCOL ] [ <restricciondecolumna>] [ ...n] <restricciondecolumna> ::= [CONSTRAINT nombrerestriccion] { [ NULL | NOT NULL ] | [ { PRIMARY KEY | UNIQUE } [CLUSTERED | NONCLUSTERED] [WITH FILLFACTOR = factorrelleno] [ON {grupoarchivos | DEFAULT} ]] ]

Page 97: IfxToJava2

97

| [ [FOREIGN KEY] REFERENCES referenciaatabla [(referenciaacolumna) ] [NOT FOR REPLICATION] ] | CHECK [NOT FOR REPLICATION] (<expresionlogica>) } <restricciondetabla> ::= [CONSTRAINT nombrerestriccion] { [ PRIMARY KEY | UNIQUE ] [ CLUSTERED | NONCLUSTERED] { ( columna[,...n] ) } [ WITH FILLFACTOR = factorrelleno] [ON {grupoarchivos | DEFAULT} ] ] | FOREIGN KEY [(columna[,...n])] REFERENCES tablareferencia [(referenciaacolumna[,...n])] [NOT FOR REPLICATION] | DEFAULT <expresionconstante> [FOR columna] | CHECK [NOT FOR REPLICATION] (<expresionlogica>) }

Estudiando con detenimiento ésta sintaxis proporcionada por SqlServer se puede observar que se deberán hacer bastantes modificaciones en la sentencia inicial proporcionada por Informix-SQL para que pueda ejecutarse sobre el gestor de bases de datos SqlServer, estas son:

Para cada cláusula se ha de crear una sentencia ALTER TALBE distinta.

Dentro de cada cláusula se admite añadir, borrar o modificar más de un campo o restricción. Cada campo que se añada, borre o modifique se separa del resto con el delimitador coma.

La cláusula MODIFY no aparece en la sentencia SqlServer, pero si hay una equivalente ALTER COLUMN, y dentro de está no permite la restricción UNIQUE ni asociar un nombre a las restricciones.

La cláusula DROP es la que más varía ya que SqlServer obliga a poner a continuación COLUMN sino entiende que es una restricción y Informix-SQL lo interpreta al revés.

SqlServer realiza más control semántico que Informix-SQL al tratar de alterar un campo, por ejemplo: no deja modificar o borrar un campo si este tiene asociado algún constraint. Estos temas semánticas no son controlados.

SINTAXIS DE ORACLE

<ALTER TABLE> ::= ALTER TABLE [ <esquema> .] nombretabla [ MODIFY ( { nombrecolumna < nuevotipotatos> [ DEFAULT <expresión> ] <restrincciondecolumna> [...n] }[,...n] ) | ADD ( { nombrecolumna <tipodato> [ DEFAULT <expresión> ] [ <restricciondecolumna> [...n]] }[,...n]) | DROP [ (nombrecolumna[,...n]) | COLUMN nombrecolumna ] | ADD [ ( <restricción de tabla> [,...n]) | <restricción de tabla > [,...n] ] | DROP CONSTRAINT nombrerestriccion ] {...n}

Page 98: IfxToJava2

98

<restricción de columna> ::= [CONSTRAINT nombrerestriccion] { [ NULL | NOT NULL ] | [ PRIMARY KEY | UNIQUE ] | CHECK ( <condicion> ) | REFERENCES <opciones de referencia> } <estado constraint> <restricción de tabla> ::= [CONSTRAINT nombrerestriccion] { [ [ NULL | NOT NULL ] | [ PRIMARY KEY | UNIQUE ] ] ( nombrecolumna[,...n] ) | <cláusula clave ajena> | CHECK ( <condicion> ) | REFERENCES <opciones de referencia> } <estado constraint>

Analizando esta sentencia se puede ver que la original de Informix-SQL se podrá adaptar al gestor de bases de datos sin mucho problema. Analizándola con detalle vemos:

Para cada sentencia ALTER TALE se podrán crear más de una cláusula y estas no irán separadas por el delimitador coma, como en Informix-SQL, sino que por un espacio.

Dentro de cada cláusula se podrán añadir, borrar o modificar más de un campo o restricción, con la excepción del borrado de restricciones, usando como separador de cada campo la coma.

Los campos que se añadan, borren o modifiquen y el añadir restricciones dentro de una misma cláusula van entre paréntesis.

La parte MODIFY de está cláusula aunque sintácticamente permite añadir constraints al campo que se modifica Oracle tiene una restricción y solo deja añadir o eliminar constraints a un campo en las secciones de está sentencia: añadir columnas y añadir restricciones.

Oracle no permite definir dos restricciones iguales sobre un campo, como por ejemplo tratar de fijar que un campo es NOT NULL cuando ya lo es o crear una clave única sobre un campo que ya tiene definida una clave única. Estas situación son irracionales pero el código fuente, Informix-SQL, las puede tener. Durante el proceso de traducción no se controlará este tipo de reglas semánticas.

SINTAXIS DE DB2

<ALTER TABLE> ::= ALTER TABLE nombretabla [ ALTER [COLUMN] nombrecolumna <modificaciondecolumna> | ADD [COLUMN] nombrecolumna <tipodato> [NOT NULL] [ <restricciondecolumna> [...n]] | ADD <restricciondetabla> | DROP [ PRIMARY KEY | [ FOREIGN KEY | UNIQUE | CHECK | CONSTRAINT ] nombrerestriccion ] {...n} <restricciondecolumna> ::= [CONSTRAINT nombrerestriccion] | [ NULL | NOT NULL ] | [ PRIMARY KEY | UNIQUE ] | CHECK ( <condición> ) | REFERENCES <opciones de referencia> <restricción de tabla> ::= [CONSTRAINT nombrerestriccion] | [ PRIMARY KEY | UNIQUE ] ( nombrecolumna[,...n] ) | FOREIGN KEY ( nombrecolumna[,...n] )

Page 99: IfxToJava2

99

| | CHECK ( <condición> ) ] <modificación de columna> ::= SET DATA TYPE { VARCHAR | CHARACTER VARING | CHAR VARING } ( entero )

Esta sentencia es la más restrictiva de todas las sentencias ALTER TABLE estudiadas hasta el momento tanto que habrá situaciones imposibles de solventar a la hora de traducir código fuente Informix-SQL a Db2. A continuación se detallan las peculiaridades y problemas encontrados:

Dentro de una misma sentencia ALTER TABLE se pueda incluir más de una cláusula utilizando como separador entre cláusulas el espacio.

La opción ADD COLUMN tiene varias restricciones a la hora de fijar constraints:

Si se usa NOT NULL obliga a fijar un valor por defecto sobre el campo. (uso de la opción: DEFAULT).

Si se utiliza UNIQUE no permite que el campo pueda tener valores nulos con lo que ha de ir acompañado de: NOT NULL y por asociación utilizar la opción: DEFAULT.

No permite eliminar columnas de la definición original de una tabla.

La opción ALTER COLUMN es muy restrictiva, no admite más que modificar campos tipo VARCHAR y solo para aumentar la longitud de los mismos, y dentro de ella no permite añadir restricciones.

No se pueden añadir constraints UNIQUE a una columna si ésta no ha sido definida como que no admite valores nulos. Y esta opción no permite añadir la restricción NOT NULL.

Para varios de los problemas, irresolubles, que se plantean con Db2 al traducir código fuente Informix-SQL no se propondrá solución práctica. En estos casos se sugiere que se revise el código genera y se adopten soluciones manuales, tales como:

Plantearse el definir todos los campos NOT NULL, en la sentencia CREATE TABLE, con objeto de evitar el fallo de las restricciones.

Para el caso de modificar o eliminar un campo solo se podría hacer creando una tabla nueva con los campos con el nuevo tipo o sin el campo eliminado y hacer un traspaso de la información de una tabla a la otra.

GENERACIOND DE CODIGO

La sentencia ALTER TABLE de Informix-SQL permite que dentro de una misma sentencia se incluya más de una cláusula, separadas por comas, y dentro de cada cláusula se pueden alterar más de un campo. Esto no es soportado por todos los gestores de bases de datos para los que se genera código, ni por el estándar SQL92. SqlServer, solo soportan una cláusula por cada sentencia y Oracle y DB2 permiten más de una usando como delimitador el espacio. Dentro de cada cláusula esta puede aplicarse sobre un solo campo o más e incluir los campos entre paréntesis o no.

La situación más restrictiva que se plantea es que en una sentencia ALTER solo se puede aplicar una cláusula y dentro de esta alterar solo un campo. Como este caso más restrictivo es soportado por todos los gestores de bases de datos se generara código así para todos los gestores no teniendo de este modo que diferenciar, en este aspecto, entre el gestor de bases de datos para el cual se genera el código. Ejemplo:

Código fuente:

Alter table prueba modify (campo1 integer, campo2 char(2)),

add (campo3 smallint, campo4 decimal(5,2))

Código objeto:

Alter table prueba modify (campo1 integer)

Alter table prueba modify (campo2 char(2) )

Page 100: IfxToJava2

100

Alter table prueba add (campo3 smallint)

Alter table prueba add (campo4 decimal(5,2) )

A nivel general hay que tener en cuenta que unos gestores utilizan los paréntesis para delimitar los campos que se alteran en las tablas y otros no. En este caso no podemos generalizar, a la hora de generar código se tendrá en cuenta para que gestor se esta haciendo y se incluirán estos o no.

Los nombres de las cláusulas no son iguales para cada gestor, habrá que poner uno u otro en función de para que gestor de bases de datos se genera código. Así para Informix y Oracle se usará: ADD, MODIFY, DROP, ADD CONSTRAINT y DROP CONSTRAINT y para SqlServer y Db2 se usará: ADD, ALTER COLUMN, DROP COLUMN, ADD CONSTRAINT, y DROP CONSTRAINT.

Otro aspecto para el que también habrá que tener en cuenta el gestor de bases de datos para el cual se está generando código son las restricciones (constraints). La sintaxis de Informix-SQL es: <restricción> CONSTRAINT nombrerestriccion sin embargo el resto de gestores de base de datos estudiados tienen la siguiente sintaxis: CONSTRAINT nombrerestriccion <restricción>.

Informix usa como restricción NOT NULL aunque no lo incluye como parte de una cláusula CONSTRAINT, el resto de gestores si la considera. Esto no causa ningún problemas puesto que una cláusula CONSTRAINT no obliga a que aparezca el nombre asociado a la restricción, con lo que el resto de los gestores lo interpretará como una restricción sin nombre asociado.

Particularidades:

Cláusula MODIFY. Informix-SQL admite como restricciones: NOT NULL y UNIQUE o DISTINCT. SqlServer y Oracle solo admiten NOT NULL, sin permitir para esta restricción asociarle un nombre, y Db2 ninguna restricción.

Aquí se planteas 3 problemas:

Para SqlServer, Oracle y Db2 no permiten añadir la restricción UNIQUE durante la cláusula MODIFY. Como solución lo que se hará es generar una sentencia ALTER TABLE adicional que cree esta restricción. Ver ejemplo:

Ejemplo1:

Sentencia original: alter table tabla1 modify(campo1 int not null unique )

Sentencias generadas para SqlServer:

alter table tabla1 alter column campo1 integer not null

alter table tabla1 add unique (campo1)

Sentencias generadas para Oracle:

alter table tabla1 modify ( campo1 integer not null )

alter table tabla1 add unique (campo1)

Sentencias generadas para Db2:

alter table tabla1 modify ( campo1 set data type integer )

alter table tabla1 add unique (campo1)

Ejemplo2:

Sentencia original:

alter table tabla1 modify(campo1 int not null unique constraint constr1)

Sentencias generadas para SqlServer:

alter table tabla1 alter column campo1 integer not null

alter table tabla1 add constraint constr1 unique (campo1)

Page 101: IfxToJava2

101

Sentencias generadas para Oracle:

alter table tabla1 modify ( campo1 integer not null )

alter table tabla1 add constraint constr1 unique (campo1)

Sentencias generadas para Db2:

alter table tabla1 modify ( campo1 set data type integer )

alter table tabla1 add constraint constr1 unique (campo1)

Generando esta sentencia adicional se consigue que el código generado tenga el mismo efecto, sobre el gestor de bases de datos destino, que el código original sobre Informix.

En el caso de que se este generando código para Db2 se mostrarán dos mensajes por pantalla: uno indicando que se revise esta sentencia ya que al ser tan restrictiva es probable que falle, y otro indicando que se revise la restricción unique ya que dependiendo como haya sido definida la columna, en la sentencia CREATE TABLE, puede fallar.

Mensajes: Warning: Revisar cláusula modify de sentencia alter table

Warning: Revisar constraints UNIQUE en cláusula modify de alter table

Db2 no admite añadir ninguna restricción dentro de esta cláusula. Para el caso de UNIQUE se adopta la opción de añadir una sentencia adicional, como se indico en el punto anterior, para el caso de NOT NULL se omitirá la generación de código de esta parte indicándolo, a través de un mensaje, durante el proceso de traducción.

Mensaje: Warning: NOT NULL no generado en cláusula modify de alter table

Db2 no permite eliminar campos. Para este gestor no se generará esta cláusula y se avisará por pantalla de tal hecho.

Mensaje: Warning: Sentencia alter table drop <campo> no generada

La palabra reservada DISTINCT no es soportada por ningún otro gestor ni por el estándar SQL92, aunque si la palabra UNIQUE, por tanto si aparece DISTINCT se sustituirá por UNIQUE durante el proceso de traducción.

La cláusula ADD CONSTRAINT varía sintácticamente entre unos gestores y otros. La sintaxis de la sentencia proporcionada por Informix-SQL en caso de etiquetar las constraints lo hace al final de la misma en cambio el resto de gestores lo hace al principio, por otro lado el resto de gestores en caso de aparecer la palabra CONSTRAINTS obliga a darle un nombre a la restricción. Por tanto la solución adoptada se ejemplifica a continuación:

Sentencia original de Informix-SQL es:

alter table tabla add constraint unique (campo1, campo2)

Se transformara para el resto de gestores como:

alter table tabla add unique (campo1, campo2)

Pero si la sentencia original es:

alter table tabla add constraint distincit (campo1, campo2) constraint restriccion1

Se transformara para el resto de gestores como:

alter table tabla1 add constraint restriccion1 unique (campo1, campo2)

Adicionalmente si se genera código para DB2 se tendrá en cuenta que esta sentencia puede fallar si no se ha definido el campo original como que no admite valores nulos. Al traducir el código fuente se notificará esta situación.

Mensaje: Warning: Revisar cláusula ADD CONSTRAINT de la sentencia alter table

Page 102: IfxToJava2

102

Cláusula DROP CONSTRAINT: todo gestor menos Informix-SQL admite borrar una sola restricción por cláusula y no colocan el nombre de la cláusula entre paréntesis.

En esta sentencia se modifican y/o crean campos lo que implica especificar el tipo de dato del mismo. La compatibilidad de los distintos tipos de datos entre los diferentes gestores de bases de datos se estudia en la sección: Estudio de Tipos de datos.

En el anexo I, en el punto: Ejemplo sentencia alter table, se muestran ejemplos de traducción de la sentencia ALTER TABLE de Informix-SQL a JAVA para cada uno de los gestores de bases de datos estuciados.

SENTENCIA BEGIN WORK

Esta sentencia marca el comienzo de una transacción. Si se producen errores, se pueden deshacer todas las modificaciones realizadas en los datos después de BEGIN para devolver los datos al último estado conocido de coherencia. Cada transacción dura hasta que se completa sin errores y se emite COMMIT, para hacer que las modificaciones sean una parte permanente de la base de datos, o hasta que se producen errores y se borran todas las modificaciones con la instrucción ROLLBACK.

Se puede incorporar una instrucción BEGIN WORK solo si no hay ninguna transacción en progreso, en caso contrario se producirá un error.

Esta sentencia no es incorporada ni por el estándar SQL89 ni por el estándar básico SQL92, aunque de una forma u otra todos los gestores de bases de datos la incorporan, incluido Informix-SQL, razón por la cual se incorpora a la hora de traducir el código fuente.

Las bases de datos Informix pueden ser creadas con o sin soporte de transacciones. Informix OL soporta varios niveles de asilamiento en las transacciones: REPETEABLE READ, CURSOR STABILITY, COMMITED READ, DIRTY READ. La versión de que se parte en este estudio: Informix SE solo soporta los niveles de aislamiento: COMMITTED READ y DIRTY READ. Si la base de datos no tiene habilitado el soporte para transacciones no se puede fijar el nivel de aislamiento.

SINTAXIS DE INFORMIX

<BEGINWORK> ::= BEGIN WORK

Cada fila que es afectada por un UPDATE, DELETE o INSERT durante una transacción es bloqueada y permanece bloqueada mientras permanezca activa la transacción.

SINTAXIS DE SQLSERVER

<BEGINWORK> ::= BEGIN [ TRAN | TRANSACTION ]

BEGIN TRANSACTION inicia una transacción local. La transacción local aumenta al nivel de transacción distribuida si se realizan una de las siguientes acciones antes de confirmarla o deshacerla:

Se ejecuta una instrucción INSERT DELETE o UPDATE que hace referencia a una tabla remota de un servidor vinculado.

Se realiza una llamada a un procedimiento almacenado remoto.

SINTAXIS DE ORACLE

Oracle no define la sentencia BEGIN WORK entiende que toda sentencia lleva implícito este comando.

Oracle realiza un autocommit antes y después de todas las sentencias DDL (Data Definition Language) las cuales son: ALTER, CREATE, DROP, GRANT, RENAME, REVOKE, TRUNCATE, etc. Las sentencias DML (Data Manipulación Lenguaje) no llevan implícito el autocommit, estas son: DELETE, INSERT, LOCK TABLE, SELECT, UPDATE, etc.

Page 103: IfxToJava2

103

Si no se utiliza la sentencia COMMIT o ROLLBACK y se finaliza la conexión de forma adecuada (se cierra esta) el sistema realiza automáticamente el COMMIT, por el contrario si se finaliza la conexión sin cerrar esta se ejecuta la sentencia ROLLBACK.

SINTAXIS DE DB2

Db2 tampoco define la sentencia BEGIN WORK y tiene un comportamiento similar al Oracle.

Cuando se ejecuta COMMIT una unidad de trabajo es procesada, los cambios son pasados a la base de datos, y otra es inicializada. Las sentencias afectadas por transacciones son: ALTER, CREATE, DELETE, DROP, GRANT, INSERT, LOCK TABLE, REVOKE, UPDTA, etc.

GENERACION DE CODIGO

De todos los gestores estudiados aquí todos ellos admiten transacciones aunque unos de forma implícita y otros explícita. Oracle, SqlServer y DB2 admiten transacciones sin hacer para ello nada especial en la base de datos sobre la cual se ejecutan las transacciones, sin embargo Informix, por defecto, considera que todas las bases de datos están en modo no transaccional.

A la hora de generar código java no se traducirá la instrucción de forma directa sino que se utilizaran las sentencias que proporciona el JDBC de JAVA para el control de transacciones. Las instrucciones a utilizar serán las siguientes:

Connection.setTransactionIsolation, que fija el nivel de asilamiento de las transacciones. JAVA soporta los siguientes niveles:

Connection.TRANSACTION_NONE . Indica que no hay transacciones.

Connection.TRANSACTION_READ_COMMITTED. Especifica que se mantengan los bloqueos compartidos mientras se leen datos para evitar lecturas no confirmadas, pero se pueden modificar los datos antes del final de la transacción, lo que provoca lecturas repetibles o datos fantasmas. Se ven solo las modificaciones ya guardadas hechas por otras transacciones. Nivel de aislamiento predeterminado.

Connection.TRANSACTION_READ_UNCOMMITTED. Implementa las lecturas no confirmadas o el bloqueo de nivel de aislamiento 0, lo que significa que no hay bloqueos compartidos y que los bloqueos exclusivos no están garantizados. Cuando se establece esta opción, es posible leer datos no confirmados, los valores pueden cambiar y pueden aparecer y desaparecer filas en el conjunto de datos antes del final de la transacción. Esta opción tiene el mismo efecto que establecer NOLOCK en todas las tablas y en todas las instrucciones SELECT de una transacción. Se trata del menos restrictivo de los cuatro niveles de aislamiento.

Connection.TRANSACTION_REPEATABLE_READ. Se establecen bloqueos para todos los datos utilizados en la consulta, lo que impide que otros usuarios los actualicen, aunque es posible insertar nuevas filas fantasmas en los datos que otro usuario establezca, de modo que se incluyan en lecturas posteriores de la misma transacción. Como la simultaneidad es inferior que el nivel de aislamiento predeterminado, sólo se debe usar esta opción cuando sea necesario.

Connection.TRANSACTION_SERIALIZABLE. Se establece un bloqueo de intervalo en el conjunto de datos, lo que impide que otros usuarios actualicen o inserten filas en el conjunto de datos hasta que finalice la transacción. Es el más restrictivo de los cuatro niveles de aislamiento. Al ser menor la simultaneidad, sólo se debe utilizar esta opción cuando sea necesario.

Connection.setAutoCommit( false ). Marca el inicio de una transacción.

Connection.setAutoCommit( true ). Marca el fin de una transacción.

Connection.rollback(). Deshace los cambios y regresa hasta la última situación estable conocida de la base de datos.

Connection.commit(). Ejecuta los cambios sobre la base de datos.

Page 104: IfxToJava2

104

Hay que tener en consideración que aunque JDBC permite seleccionar un nivel de aislamiento hacer esto no tendrá ningún efecto a no ser que el driver del controlador de la base de datos lo soporte. Informix, SqlServer y Db2 admite todos los niveles de aislamiento, sin embargo Oracle solo admite READ_COMMITTED y SERIALIZABLE.

El comportamiento general de los programas es que cada sentencia individual se trate como una transacción y está será pasada al gestor de bases de datos nada más ser ejecutada. Si se pretende que dos o más sentencias sean agrupadas en una transacción se deben de utilizar las sentencias de manejo de transacciones: BEGIN WORK, COMMIT y ROLLBACK. El nivel de aislamiento que se establece por defecto en los gestores de bases de datos es READ_COMMITTED.

Para reflejar el comportamiento por defecto de los gestores al principio de cada programa generado, durante del proceso de traducción, se fijará el nivel de aislamiento y se activará el modo auto-entrega (autocommit) de tal forma que cada sentencia sea considerada una transacción. Esto se realizará dentro del método: HayTransac() justo después de establecer la conexión con la base de datos, esta método contendrá básicamente las instrucciones JAVA:

Conection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

Conection.setAutoCommit (true);

Esta sentencia, para el caso que el gestor de bases de datos sea Informix puede producir un error si la base de datos no esta en modo transaccional y en este caso las sentencia ROLLBACK Y COMMIT no tienen sentido. Para este gestor no se omitirá la generación de código de las sentencias que manejan transacciones pero si se desactivará la generación de errores haciendo que así, que en caso de que el mismo este en modo no transaccional, no se vea afectado el funcionamiento del programa.

Cuando se decide por programa utilizar transacciones el flujo de sentencias Informix será:

BEGIN WORK

[ sentencias SQL ]

COMMIT WORK o ROLLBALLWORK

Este se traducirá a sentencias JAVA:

Connection.setAutoCommit(false); //desactiva el modo auto-commit

[ sentencias SQL ]

Si la transacción no se da por correcta:

Connection.rollback();

Connection.setAutoCommit (true);

Si la transacción se da por correcta:

Connection.commit();

Connection.setAutoCommit (true);

En la sección SENTENCIA COMMIT (Sentencia COMMIT WORK) se muestra un ejemplo del uso de transacciones

SENTENCIA CLOSE

Cierra un cursor abierto liberando el conjunto de resultados actual y todos los bloqueos mantenidos sobre las filas en las que estaba colocado el cursor.

Esta sentencia esta soportada por el estándar SQL89 y por consiguiente por el SQL92.

Page 105: IfxToJava2

105

SINTAXIS DE INFORMIX

<CLOSE> ::= CLOSE nombredecursor

SINTAXIS DE SQLSERVER

<CLOSE> ::= CLOSE { { [GLOBAL] nombrecursor } | nombrevariablecursor}

SINTAXIS DE ORACLE

<CLOSE> ::= CLOSE nombredecursor | <variablecursor>

SINTAXIS DE DB2

<CLOSE> ::= CLOSE nombredecursor [ WITH RELEASE ]

GENERACIÓN DE CÓDIGO

Como se ve esta sentencia es definida, con igual sintaxis que Informix-SQL, por el resto de gestores.

En la sección: Sentencias de manipulación dinámica de datos y cursores se mostrarán ejemplos de esta sentencia, junto con el resto de sentencias de manejo de cursores, así como las peculiaridades de su traducción a código objeto.

SENTENCIA CLOSE DATABASE

Esta sentencia cierra la conexión con la base de datos.

Esta sentencia no es soportada por el estándar SQL89 y tampoco por el SQL92 y es una ampliación que Informix-SQL añade a su versión 4.10 y el resto de gestores de bases de datos estudiados, de una u otra forma, implementan algún sistema de desconexión con la base de datos aunque no se ajustan en ningún caso a la sentencia de Informix-SQL.

SINTAXIS DE INFORMIX

<CLOSE DATABASE> ::= CLOSE DATABASE

GENERACIÓN DE CODIGO

Dado que el código que se genera es JAVA , el cual permite establecer conexiones con las bases de datos, y que no existe una traducción directa de la sentencia original al resto de gestores de bases de datos se interpretará esta sentencia como el cerrar la conexión que, hasta el momento, había abierta con la base de datos.

Las conexiones se establecen con la base de datos usando el JDBC de java que posibilita una forma de acceso a una base de datos vía JDBC y ODBC. La clase que controla esto es: Connection del paquete java.sql y suministra un método que permite cerrar las conexiones: java.sql.Connection.close(). Por tanto cuando en el código fuente encontremos una sentencia CLOSE DATABASE se traducirá en cerrar la conexión actual a la base de datos.

En el Anexo I, en el punto: Ejemplo sentencias conexión/desconexión se muestra el código fuente y objeto de un programa en el que se tratan las sentencias de conexión y desconexión con la base de datos. Al tratarse de sentencias basadas en los estándares de conexión/desconexión definidos por el API JDBC de JAVA el código objeto será igual independientemente del gestor de bases de datos destino.

Si se observa el código objeto generado se puede ver que no se hace referencia directamente a la clase java.sql.Connection. Se han embebido todas las funciones de conexión a la base de datos en una clase propia llamada: AccesDB y dentro de esta se han definido las funciones:

Page 106: IfxToJava2

106

new AccesDB("datos") se encarga de establecer la conexión por primera vez a la base de datos al tiempo que inicializa la clase.

ASGdb.iniConexionDB("datos2") establece la conexión con la base de datos.

ASGdb.finConexionDB() finaliza la conexión actual con la base de datos.

SENTENCIA COMMIT WORK

Esta sentencia marca el fin de una transacción correcta y hace que todas las modificaciones efectuadas sobre los datos desde el inicio de la transacción pasen a formar parte permanente de la base de datos.

Esta sentencia no es incorporada ni por el estándar SQL89 ni por el estándar básico SQL92 aunque todos los gestores de bases de datos la incorporan, incluido Informix-SQL, razón por la cual se incorpora a la hora de traducir el código fuente.

Al igual que ocurría con la sentencia BEGIN WORK cada gestor incorpora su propia sentencia pero la solución que se adoptará a la hora de generar código es independiente del gestor y se basa en las posibilidades que aporta el JDBC de JAVA. Por esta razón no nos pararemos a estudiar en detalle la sentencia del resto de gestores.

SINTAXIS DE INFORMIX

<COMMIT WORK> ::= COMMIT WORK

GENERACIÓN DE CODIGO

La generación de código, al igual que con la sentencia BEGIN WORK, se hace de forma independiente al gestor de base de datos para el cual se este traduciendo. La traducción será la siguiente:

Connection.commit()

Connection.setAutoCommit( true )

Este código hace dos acciones, primero hace que la modificaciones efectuadas, en la base de datos, desde el inicio de la transacción pasen a forma parte de la base de datos de forma permanente; y segundo cierra la transacción.

El código objeto obtenido de las sentencias de tratamiento de transacciones no será dependiente del gestor de bases de datos ya que se utilizan funcionalidades propias del API JDBC. En el punto: Ejemplo sentencias de tratamiento de transacciones, perteneciente al Anexo I se muestran ejemplos prácticos.

SENTENCIA CREATE AUDIT

Permite crear un log para una tabla de la base de datos.

Esta sentencia no es soportada, de igual modo que Informix-SQL, por ningún otro gestor de bases de datos aunque de una forma u otra todo gestor de bases de datos mantiene un log de las operaciones que se hacen sobre la base de datos. El estándar SQL89 no la contempla e Informix-SQL tampoco en su versión 4.10, la incorpora como una ampliación.

SINTAXIS DE INFORMIX

<CREATEAUDIT>::= CREATE AUDIT FOR [ nombretabla | nombresinonimo] ON �path�

GENERACIÓN DE CÓDIGO

Esta es una sentencia de administración la cual se suele ejecutar directamente sobre la herramienta de administración, su uso dentro de un programa es nulo, no es soportada por ningún otro gestor de base de datos, y tampoco por ningún estándar por esta razón no se traducirá a

Page 107: IfxToJava2

107

código objeto. Si aparece en el código fuente se indicará por pantalla, durante el proceso de traducción, el no procesamiento de la misma con el siguiente mensaje:

Mensaje: Warning: Sentencia créate audit. no generada

SENTENCIA CREATE DATABASE

Esta sentencia permite crear una base de datos. El nombre de la base de datos debe de ser único dentro del gestor de base de datos en el que se crea. El gestor de base de datos crea el catalogo del sistema el cual contiene el diccionario de datos.

Una cosa a tener en cuenta, a nivel de programación, es que para crear una base de datos nueva primero a de haber una conexión con el gestor de bases de datos (lo que implica con otra base de datos existente). Una vez creada la base de datos esta pasa a ser la base de datos actual.

Para poder crear la base de datos en necesario tener los privilegios suficientes y al tiempo de hacer esto, en algunos gestores, será preciso crear: usuarios, esquemas, etc.

Esta sentencia no es contemplada por el estándar SQL89, Informix-SQL lo amplia al usarla, tampoco es soportada por el SQL92 aunque de una forma u otra todo gestor de bases de datos la implementa.

SINTAXIS DE INFORMIX

<CREATE DATABASE> ::= CREATE DATABASE nombrebasedatos [ WITH LOG IN �nombrearchivo� [ MODE ANSI] ]

La opción WITH NO LOG permite crear una base de dates en modo transaccional. El archivo: nombrearchivo es usado para guardar las transacciones mientras estas no forman parte de forma definitiva de la base de datos.

SINTAXIS DE SQLSERVER

<CREATEDATABASE> ::= CREATE DATABASE nombrebasedatos [ ON [PRIMARY] [ <ficheroespecificaciones> [,�n] ] [, <grupoarchivos> [,�n] ] ] [ LOG ON { <ficheroespecificaciones> [,�n]} ] [ FOR LOAD | FOR ATTACH ] <ficheroespecificaciones> ::= ( [ NAME = nombrearchivológico, ] FILENAME = 'nombrearchivo' [, SIZE = tamaño] [, MAXSIZE = { tamañomáximo | UNLIMITED } ] [, FILEGROWTH = incrementocrecimiento] ) [,�n] <grupoarchivos>::= FILEGROUP nombregrupoarchivos <ficheroespecificaciones> [,�n]

En la sintaxis de SqlServer admite especificar muchas más opciones que la original, de Informix-SQL, de la que partimos. El propio gestor de base de datos es capaz de crear la base de datos indicándole exclusivamente el nombre de la base de datos, el resto de valores se inicializan con los valores predeterminados.

SINTAXIS DE ORACLE

<CREATEDATABASE> ::= CREATE DATABASE nombrebasedatos [DATABASE_ID númeroentero] [DATABASE_SIZE númeromegas] [EXTENT_SIZE númerokbs ]

Page 108: IfxToJava2

108

La sentencia de Oracle soporta muchos más parámetros que Informix. Pero si estos no se ponen, como será el caso, tomará los valores prefijados por defecto para el gestor de bases de datos.

SINTAXIS DE DB2

<CREATEDATABASE> ::= CREATE [DATABASE | DB] nombrebasedatos [ [AT NODE ] | [ <createdatabaseoptions>] ] <createdatabaseoptions> ::= ON [camino | unidad ] | ALIAS aliasdebasededatos | USING CODESET codeset TERRITRY territorio | COLLATE USING [ SYSTEM | COMPATIBILITY IDENTITY ] | NUMREGS númeroregistros | DFT_EXTENT_SZ defaulextencion | CATALOG TABLESPACE tablespacedefinicion | USER TABLESPACE tablespacedeusuario | TEMPORALY TABLESPACE tablespacetemporal | WITH �cadenacaracteres�

Al igual que ocurría con los gestores de bases de datos SqlServer y Oracle, Db2 admite una sintaxis mucho mas completa que la que admite Informix-SQL.

GENERACION DE CODIGO

Esta es una sentencia de administración que no se ejecuta desde un programa y en algunos casos incluso ni siquiera es posible, siempre se crean las bases de datos a través de la herramienta de administración ya que cada gestor tienes sus peculiaridades.

Si se observa con detenimiento la sentencia de Informix-SQL podemos considerar dos partes diferenciadas, la primera que la subsentencia que crea la base de datos propiamente dicha, y la segunda, la cual es exclusiva de Informix-SQL y de su motor SE, que permite especificar que la base de datos que se crea va a admitir transacciones. Por tanto a la hora de traducir la sentencia se pueden dar dos situaciones:

1.- Que la sentencia original sea: CREATE DATABASE nombrebasedatos. La traducción a los gestores destino sería inmediata, aunque debe tenerse en cuenta que hay gestores que no admiten lanzar esta sentencia desde una conexión JDBC, como es el caso de: Oracle y Db2.

2.- Que la sentencia original incluya la cláusula : WITH LOG IN ..... En este caso esta segunda parte será omitida a la hora de traducir la sentencia a no ser que el código destino se vaya a ejecutar contra el gestor de bases de datos de Informix-SQL (motor SE), debido a que el restos de gestores estudiados al crear las bases de datos ya la entiende como transaccionales.

Se ha de tener en cuenta que para que esta sentencia se ejecute sobre el gestor de bases de datos destino se ha de tener suficientes privilegios sobre el mismo, a continuación se muestran algunos detalles a tener en cuenta si se pretende incluir esta sentencia dentro de un programa:

Informix. El usuario que lanza la sentencia a de administrador de la bases de datos: informix u otro perteneciente al grupo Informix-Admin. Por defecto se crea la base de datos en modo no transaccional.

SqlSever. El usuario ha de ser sysadm. Para este gestor hay que tener en cuenta que tras crear la base de datos no se conecta automáticamente a ella como ocurre con Informix, esto se tendrá en cuenta al generar código añadiendo la sentencia de conexión a la nueva base de datos en el mismo.

Oracle. Aunque es posible la sentencia a generar debe incluir mucha información adicional como: lugar de los tablespaces de datos, de log, etc. Información que no se extrae del código fuente con lo cual es altamente recomendable no usarla.

Db2. Aunque admite la sentencia obliga a que para ser ejecutada no se este conectado a la ninguna base de datos lo cual impide de todas formas el lanzar la sentencia desde un programa JAVA.

Page 109: IfxToJava2

109

SENTENCIA CREATE INDEX

Esta sentencia permite crear un índice para una o más columnas de una tabla determinada. Sólo el propietario de la tabla, o un usuario con suficientes privilegios, puede crear índices en ella. El propietario de una tabla puede crear un índice en cualquier momento, independientemente de que haya datos en la tabla o no.

SITAXIS DE INFORMIX

<CREATEINDEX> ::= CREATE [UNIQUE|DISTINCT] [CLUSTER] INDEX nombreindice ON nombretabla ( {nombrecolumna [ASC| DESC]} [,...n] )

UNIQUE y DISTINCT son sinónimos y en caso de especificar uno de ellos no se permitirán valores duplicados para las columnas que se indexan. La opción CLUSTER obliga a que las filas de la tabla se ordenen en función de los valores de las columnas indexadas. ASC/DESC permite especificar una restricción de los valores que tome la columna indexada, obligando a que tengan valores ascendentes (por defecto) o descendentes.

Esta sentencia no cumple el estándar SQL92 aunque todos los gestores aquí estudiados la incorporan con sus propias particularidades.

SINTAXIS DE SQLSERVER <CREATEINDEX> ::= CREATE [UNIQUE] [ CLUSTERED | NONCLUSTERED ] INDEX nombreindice ON nombretabla ( nombrecolumna [ASC |DESC ] [,�n]) [ INCLUDE ( nombrecolumna [ ,...n ] ) ] [ WITH ( <indice_relacional_opcional> [ ,...n ] ) ] [ ON { nombreesquema ( nombrecolumna ) | Nombregrupoficheros | default } ]

SINTAXIS DE ORACLE

<CREATEINDEX> ::= CREATE [UNIQUE] INDEX [<esquema>] nombreindice ON [<esquema>] nombretabla ( {nombrecolumna [ASC|DESC]} [,...n] ) Esquema representa el nombre de una colección de objetos de la base de datos.

SINTAXIS DE DB2

<CREATEINDEX> ::= CREATE [UNIQUE] INDEX nombreindice ON nombretabla ( {nombrecolumna [ASC|DESC]} [,...n] ) [SPECIFICATION ONLY] [ INCLUDE ( {columna [ASC|DESC]} [,...n] ) ] [CLUSTER | EXTED USING nombreextensionindice [ ( {expresionconstante [,...n] ) ] ] [PCTFREEE [10|númeroentero] ] [MINPCTUSED númeroentero] [ DISALLON REVERSE SCANS | ALLOW REVERSE SCANS ]

GENERACIÓN DE CODIGO

Si se observa la sentencia original de Informix-SQL y aquellas a las que se trata de traducir se puede ver que todos los gestores estudiados la soportan casi en su totalidad además aportan sus propias funcionalidades.

Los únicos problemas que se plantean están en las opciones CLUSTER, UNIQUE/DISTINCT. CLUSTER no es soportada por ningún otro gestor y se omitirá su traducción. La opción DISTINCT que incorpora Informix-SQL no existe para el resto de gestores pero al ser equivalente a UNIQUE, que si es incorporada por todos los gestores, se sustituirá por esta.

El omitir el parámetro CLUSTER no plantea ningún problema en el funcionamiento normal de cada gestor de bases de datos solo se ocasionan pequeñas variaciones en la eficiencia de las búsquedas.

Page 110: IfxToJava2

110

En el Anexo I se muestra un ejemplo de la traducción de esta sentencia, ver: Ejemplo sentencia creacion indice-

SENTENCIA CREATE SYNONYM

Crea un sinónimo para una tabla o vista.

Esta sentencia no es soportada por el estándar SQL89 y tampoco por el SQL92, aunque Informix-SQL la incorpora como una aplicación a su versión 4.10. Todos los gestores en las versiones mínimas indicadas la contemplan. SqlServer la incorpora por primera vez en la versión 2005.

SINTAXIS DE INFORMIX

<CREATESYNONYM> ::= CREATE SYNONYM nombresinonimo FOR [nombretabla | nombrevista ]

Informix-SQL define los sinónimos como públicos lo que implica que dicho sinónimo puede ser utilizado por cualquier usuario de la base de datos.

Si desaparece el objeto sobre el que se creo el sinónimo de la base de datos éste desaparece también. Informix no permite crear dos sinónimos con el mismo nombre aunque sea sobre distinto objeto.

SINTAXIS DE SQLSERVER

<CREATESYNONYM> ::= CREATE SYNONYM [ esquema . ] nombresinonimo FOR nombreobjeto

Donde nombreobjeto: procedimiento almacenado, función, vista o tabla definida por el usuario.

No es necesario que el objeto base exista en el momento de crear el sinónimo. SQL Server comprueba la existencia del objeto base en tiempo de ejecución.

No se necesitan permisos en el objeto base para compilar correctamente la instrucción CREATE SYNONYM, porque la comprobación de los permisos para el objeto base no se realiza hasta el momento de la ejecución.

La definición del sinónimo persiste aunque la tabla sobre el que se definió desaparezca. Si se crea un sinónimo con igual nombre a otro ya existente permanece la definición del último.

SINTAXIS DE ORACLE

<CREATESYNONYM> ::= CREATE [ PUBLIC ] SYNONYM [ <esquema> ] nombresinonimo FOR [ <esquema> ] <nombreobjeto> <nombreobjeto> ::= nombretabla | nombrevista | secuencia | sinónimo

En caso de no poner explícitamente la opción PUBLIC se entiende que es privado. Un sinónimo privado solo podrá ser utilizado por el usuario que lo definió.

La definición del sinónimo persiste aunque desparezca el objeto inicial al que hacía referencia. En caso de que se defina dos sinónimos con igual nombre, aunque sea sobre distinto objeto, no se produce ningún error y será valida la última definición del sinónimo.

SINTAXIS DE DB2

<CREATESYNONYM> ::= CREATE [ ALIAS | SYNONYM ] nombresinonimo FOR <nombreobjeto> <nombreobjeto> ::= nombretabla

Page 111: IfxToJava2

111

| nombrevista | nickname | sinónimo

Un nickname es un identificador que hace referencia a una porción de código fuente.

El acceso al sinónimo será el mismo que el que tenga el objeto del cual se crea el sinónimo.

Si se elimina de la base de datos el objeto al que hace referencia el sinónimo éste se mantiene en la misma. Esto puede provocar errores de ejecución de programas.

Si se crea dos sinónimos con igual nombre será valida la última definición.

GENERACIÓN DE CÓDIGO

Esta sentencia es soportada por todos los gestores de bases de datos aquí estudiados.

Consideraciones a tener en cuenta:

Existe distinto comportamiento entre Informix y el resto de gestores en cuanto a la redefinición de un sinonino (crear otro sinónimo con el nombre de uno que ya existe). Informes no lo permite y el resto sí. Como los programas originales se entiende son correctos para Informix no se plantea ningún problema de consistencia a la hora de ejecutar los programas, traducidos, sobre el resto de gestores, no se podrá producir este caso.

Debido a la diferente interpretación que hacen los distintos gestores de bases de datos de la sentencia DROP TABLE (ver página 124), se puede estar intentado crear un sinónimo que ya existe. Para solucionar este problema hay varias alternativas:

1. Intentar averiguar los sinónimos asociados a la tabla que se va a borrar y borrar estos.

2. Mantener una estructura suplementaria con los sinónimos que se han creado y sobre que tablas se creado para cuando se borre esta última borrar los primeros.

3. Antes de crear un sinónimo hacer, controlando no se generen errores, un DROP del mismo.

De las tres soluciones las dos primeras se desechan bien por coste en tiempo de ejecución o inviabilidad de las misma ya que no todo sinónimo se genera desde un programa. La tercera alternativa es la que más se ajusta al comportamiento del programa origina sobre el gestor original, ya que sí sobre Informix se elimina la tabla la definición del sinónimo sobre la misma desaparece y por otro lado tampoco permite dos sinónimos con el mismo nombre. Por tanto a la hora de generar código para el resto de gestores se añadirá una sentencia DROP SYNONYM antes de la creación del mismo.

En el apartado: Ejemplo sentencia creacion de sinonimo, del Anexo I se muestran ejemplos de la traducción de esta sentencia para ser ejecutada sobre cada uno de los gestores de bases de datos estudiados.

SENTENCIA CREATE TABLE

Permite definir una tabla en la base de datos. La definición debe incluir su nombre así como el nombre y atributos de sus columnas. La definición también puede incluir otros atributos de la tabla, tales como: clave primaria y restricciones.

Esta sentencia esta soportada por el estándar SQL92. Estudiando en detalle la sentencia que definen los distintos gestores de bases de datos se pude ver que estos no soportan en su totalidad el estándar aunque si se ajustan bastante a él.

Esta sentencia también permite la creación de tablas temporales. Las tabla temporales solo pueden ser vistas por el usuario que creo dicha tabla y su vida es la misma que la aplicación desde la cual se creo. Cuando se sale de la aplicación, se finaliza la sesión, que creo la tabla temporal esta se elimina automáticamente.

Page 112: IfxToJava2

112

Las tablas temporales deben tener distinto nombre que una tabla, vista o sinónimo existente en la base de datos actual. Sin embargo pueden tener el mismo nombre que otra tabla temporal creada por otro usuario.

SINTAXIS DE INFORMIX

<CREATETABLE> ::= CREATE [ TEMP ] TABLE nombretabla <lista de elementos de la tabla> [ IN �camino� ] <lista de elementos de la tabla> ::= ( <elemento de la tabla> [, ... n] ) <elemento de la tabla> ::= <definición de columna> | <restricción de tabla> <definición de columna> ::= nombrecolumna <tipodatosql> [NOT NULL] [<restricciones de columna> ] <restricciones de columna> ::= [ UNIQUE|DISTINCT] [ CONSTRAINT nombrerestriccion ] <restricción de tabla> ::= { [UNIQUE|DISTINCT] (nombrecolumna [,�n]) } [ CONSTRAINT nombrerestriccion ]

La opción IN �camino� permite indicar la ubicación física de la tabla, sino se especifica ninguna se creará: las tablas temporales donde indique la variable de entorno DBTEMP y las otras donde este creada la base de datos lo cual viene indicado por la variable de entono DBPATH. Si alguna de estas variables de entorno no están declaradas las tablas se crearan en el lugar desde el cual se ejecuta la sentencia.

SINTAXIS DE SQLSERVER

<CREATETABLE> ::= CREATE TABLE [ nombrebasedatos. [ propietario.] | propietario. ] nombretabla ( { <definicion de columna> | nombredecolumna AS expresión | <restricción de tabla> } [, ...n ] ) [ ON { grupodeficheros | DEFAULT } ] [ TEXTIMAGE_ON { grupodeficheros | DEFAULT } ] <definición de columna> ::= { nombrecolumna tipodatosql } [ COLLATE < nombrecollate > ] [ [ DEFAULT expresioncte ] | [ IDENTITY [ (semilla , incremento) [ NOT FOR REPLICATION ] ] ] ] [ ROWGUIDCOL] [ <restricción de columna> ] [ ...n ] <restriccióndecolumna> ::= [ CONSTRAINT nombrerestriccion ] { [ NULL | NOT NULL ] | [ { PRIMARY KEY | UNIQUE } [ CLUSTERED | NONCLUSTERED ] [WITH FILLFACTOR = número] [ON {grupodeficheros| DEFAULT} ] ] ] | [ [ FOREIGN KEY ] REFERENCES tablareferencia [ ( columnareferencia ) ] [ ON DELETE { CASCADE | NO ACTION } ] [ ON UPDATE { CASCADE | NO ACTION } ] [ NOT FOR REPLICATION ]

Page 113: IfxToJava2

113

] | CHECK [ NOT FOR REPLICATION ] ( expression ) } <restriccióndetabla> ::= [ CONSTRAINT nombrerestriccion ] { [ { PRIMARY KEY | UNIQUE } [ CLUSTERED | NONCLUSTERED ] { ( columna [ ASC | DESC ] [ ,...n ] ) } [WITH FILLFACTOR = número] [ ON { grupodeficheros | DEFAULT } ] ] | FOREIGN KEY [ ( columna [ ,...n ] ) ] REFERENCES tablareferencia [ ( columnareferencia [ ,...n ] ) ] [ ON DELETE { CASCADE | NO ACTION } ] [ ON UPDATE { CASCADE | NO ACTION } ] [ NOT FOR REPLICATION ] | CHECK [ NOT FOR REPLICATION ] ( expresion ) }

SqlServer permite crear tablas temporales locales y globales. Las tablas temporales locales son visibles sólo en la sesión actual; las tablas temporales globales son visibles para todas las sesiones.

Para definir una tabla temporal se coloca un prefijo de signo numérico simple (#nombretabla) en los nombres de las tablas temporales locales y un prefijo de un signo numérico doble (##nombretabla) en los nombres de las tablas temporales globales.

Si se crea una tabla temporal local en un procedimiento almacenado o una aplicación que varios usuarios pueden ejecutar al mismo tiempo, SqlServer es capaz de distinguir las tablas creadas por los distintos usuarios. SqlServer hace esto al anexar internamente un sufijo numérico a cada nombre de tabla temporal local. El nombre completo de una tabla temporal tal como se almacena en la tabla sysobjects de tempdb consta del nombre de la tabla especificado en la instrucción CREATE TABLE y el sufijo numérico generado por el sistema. Para permitir que se agregue el sufijo, el nombretabla especificado de un nombre temporal local no puede exceder de 116 caracteres.

Las tablas temporales se eliminan automáticamente cuando están fuera de ámbito.

Si no se especifica el usuario por defecto, Sqlserver, creará la tabla con el propietario dbo aunque hayamos iniciado sesión con otro diferente.

SINTAXIS DE ORACLE

<CREATETABLE> ::= CREATE [GLOBAL TEMPORARY] TABLE [ <esquema> . ] nombretabla <lista de elementos de la tabla> <lista de elementos de la tabla> ::= ( <elemento de la tabla> [, ... n] ) [ ON COMMIT {PRESERVER | DELETE } ROWS ] <elemento de la tabla> ::= <definicion de columna> | < restricción de tabla > <definicion de columna> ::= nombrecolumna <tipodatosql> [DEFAULT expresión] [<restricciones de columna> ] <restricciones de columna> ::= [ CONSTRAINTS nombrerestriccion ] { [NOT] NULL | [ UNIQUE | PRIMARY KEY ] | <cláusula referencia> | <cláusula chek> }

Page 114: IfxToJava2

114

<cláusula referencia> ::= REFERENCES <esquema> nombretabla [ ( nombrecolumna [,�n] ) ] [ ON DELETE CASCADE] <cláusula check> ::= CHECK ( <condición> ) < restricción de tabla > ::= [ CONSTRAINTS nombrerestriccion ] { [NOT] NULL | [ UNIQUE | PRIMARY KEY ] { ( columna [ ,...n ] ) | FOREIGN KEY ( columna [ ,...n ] ) <cláusula referencia> | <cláusula chek> }

En oracle también se permite la creación de tablas temporales, para ello se ha de indicar utilizando las palabras reservadas GLOBAL TEMPORARY. La definicion de la tabla es visible por todas las sesiones del mismo usuario. Los datos de la tabla temporal son solo visibles por la sesión que inserto los datos en la misma.

En oracle la definición de una tabla temporal persiste, de igual modo que las tablas normales, para el usuario que la creo, pero su contenido tiene una vida limita que puede ser mientras dure la transacción o la sesión. Se especifica la vida de los datos en la tabla temporal con la cláusula ON COMMIT. Si es seguida de la opción PRESERVE la vida de los datos es mientras este activa la sesión en caso contrario, opción DELETE, la vida es hasta el fin de la transacción en curso. Sino se especifica explícitamente la cláusula ON COMMIT se asume por defecto que los datos se mantienen en la tabla temporal mientras dure la transacción.

SINTAXIS DE DB2

<CREATETABLE> ::= CREATE [SUMMARY] TABLE nombretabla <lista opciones de la tabla> [ DATA CAPTURE NONE | DATA CAPTURE CHANGES] [ IN nombretablespace [<opciones de talespace>] ] [ PARTITIONING KEY ( nombrecolumna [,�n] USING HASHING) | REPLICATED ] [ NOT LOGGED INITIALLY] <lista opciones de la tabla> ::= <lista de elementos de la tabla> | OF nombretipo [ <opcionestipotabla>] | <resumen de definición de tabla> | LIKE [ nombretabla1 | nombrevista1 | nomnbrenick] [<opcionesdecopia>] <lista de elementos de la tabla> ::= ( <elemento de la tabla> [, ... n] ) <elemento de la tabla> ::= <definición de columna> | <restricción de tabla> <definicion de columna> ::= nombrecolumna <tipodatosql> [<restricción de columna> ] <restricción de columna> ::= NOT NULL | [LOGGED|NOT LOGGED] [COMPACT|NOT COMPACT] | CONSTRAINT nombrerestriccion [ [ UNIQUE | PRIMARY KEY ] | <cláusula referencia> | <cláusula chek> ] <cláusula referencia> ::= REFERENCES nombretabla [ ( nombrecolumna [,�n] ) ] [<reglasclausula>] <reglasclausula> ::= [ ON DELETE NO ACTION | ON DELETE [RESTRICT|CASCADE|SET NULL] ] [ ON UPDATE NO ACTION | ON UNPDATE RESTRICT]

Page 115: IfxToJava2

115

<cláusula check> ::= CHECK ( <condición> ) <restriccióndetabla> ::= <restricción única> | <restricción referencial> | <restricciones check> <restricción única> ::= [CONSTRAINTS nombrerestriccion] {UNIQUE|PRIMARY KEY} ( nombrecolumna [,�n]) <restricción referencial> ::= CONSTRAINTS nombrerestriccion] FOREIGN KEY ( nombrecolumna [,�n]) <cláusula referencia> <restricción check> ::= [CONSTRAINTS nombrerestriccion] CHECK (concidioncheck)

La creación de tablas temporales es admitida pero no con la sentencia CREATE sino con la DECLARE que se especifica a continuación.

<CREATETABLE>::= DECLARE GLOBAL TEMPORARY TABLE nombretabla <lista opciones de la tabla> [WITH REPLACE] [ON COMMIT DELETE ROWS | ON COMMIT PRESERVE ROWS] [NOT LOGGED][IN nombretablespace ] [ PARTITIONING KEY ( nombrecolumna [,�n] USING HASHING) ] <lista opciones de la tabla>::= <lista de elementos de la tabla> | LIKE [ nombretabla1 | nombrevista1] [<opcionesdecopia>] | AS ( <sentenciaselectcompleta> ) [<opcionesdecopia>] <lista de elementos de la tabla> ::= ( <elemento de la tabla> [, ...n] ) <elemento de la tabla> ::= nombrecampo <tipodatosql> [<definición de opciones de columna> ] <definicion de opciones de columna> ::= NOT NULL | [WITH] DEFAULT [valordefecto]

La sentencia DECLARE GLOBAL TEMPORARY TABLE define una tabla temporal para la sesión actual. La definición de la tabla temporal declarada no aparece en el catalogo del sistema no es permanente y no puede ser compartida con otras sesiones. Cada sesión que define una tabla temporal con el mismo nombre tiene su propia y única descripción de la tabla temporal. Cuando una sesión termina las filas de la tabla temporal son borradas y la definición de la tabla temporal es eliminada.

Db2 tiene más limitaciones a la hora de crear las tablas temporales que las normales ya que no admite la definición de restricciones sobre las mismas a excepción de NOT NULL.

GENERACIÓN DE CODIGO

Esta sentencia se puede ver como dos claramente diferenciadas: la creación de tablas temporales, y la creación de tablas normales.

En la creación de tablas normales la sentencia original de Informix-SQL es altamente compatible con cualquier otro gestor de bases de datos. A nivel general solo se plantean 2 problemas:

La definición de constraints. Esta definición es igual a la que había en la sentencia ALTER TABLE (ver página 99) y por lo tanto el estudio realizado en dicha sección es idénticamente valido para ésta.

La opción �IN caminio� de la sentencia CREATE TABLE no es soportada por ningún otro gestos de bases de datos en el mismo sentido que la entiende Informix-SQL. Como se explicó en la definición de la sentencia �camino� indica el path en el cual se define la tabla, éste es una dirección física dentro del sistema operativo en la cual se creará uno o más archivos que contendrán la información de la tabla de la base de datos. El resto de gestores de bases de datos estudiados contienen administradores más avanzados a través de los cuales se indica la ubicación del espacio de datos en el cual se almacenan todas las tablas.

Page 116: IfxToJava2

116

Debido a que ningún otro gestor asocia un nombre de fichero físico a una tabla y a que a través de su administrador se especifica un espacio de datos común para todas las tablas esta opción: �IN camino� se omitirá para ellos. En caso de informix se atenderá a la variable de entorno DBPATH.

DB2, como se comento al tratar la sentencia ALTER TABLE, no permite añadir una constraint UNIQUE a un campo si este admite valores NULOS. Este problema es difícil de controlar y corregir a la hora de realizar el proceso de traducción de código ya que por un lado el añadir esta restricción puede realizarse de forma independiente a la definición de la columna y por otro el añadir la cláusula NOT NULL en la definición de la columna significa que se está variando la definición de la tabla realizada en el código fuente original. En el proceso de traducción, con objeto de intentar evitar errores al ejecutar el programa resultante, se añadirá la cláusula NOT NULL solo si aparece UNIQUE durante la definición del campo. Ejemplo:

Fuente Informix:

create table tabla1 (

campo1 smallint,

campo2 char(10) unique,

distinct (campo1) constraint constr1,

���� )

Código objeto Db2:

create table tabla1 ( campo1 smallint ,

campo2 char(10) not null unique ,

constraint constr1 unique ( campo1 ),

��� )

Como se puede observar al definir el campo2 se le añade la condición NOT NULL debido a que al tratar el campo se puede tomar esa decisión, pero no ocurre lo mismo con el campo1 y posteriormente al intentar crear la restricción se producirá un error sino existe una revisión posterior del código generado.

El resto de la sentencia original de Informix-SQL es completamente aceptado por los demás gestores de bases de datos estudiados. Sólo queda analizar si los tipos de datos de Informix-SQL son compatibles y/o soportados por el resto de gestores lo cual se estudiará en la sección: Estudio tipos de datos (ver página 154).

En el Anexo I, en el punto: Ejemplo sentencia, se muestra un ejemplo del uso del traductor aplicado a esta sentencia.

En cuanto a la generación de tablas temporales hay más peculiaridades que analizar. Aparte de que sintácticamente se definan de forma distinta algo muy importante a estudiar es la semántica de la definición. Todos los gestores, y particularmente Informix-SQL, entienden que cuando se finaliza el programa que creo la tabla temporal esta desaparece totalmente: datos y definición a excepción de Oracle en el cual la definición de la tabla perdura en el tiempo, esto plantea un problema bastante difícil de salvar al intentar trasformar la sentencia original de Informix-SQL a Oracle con la misma semántica.

Sintácticamente la definición de Informix-SQL de las tablas temporales es más simple que la de las tablas normales, como se detalla a continuación:

Incorpora el token TEMP precediendo al token TABLE. El resto de gestores no lo incorporan pero adoptan otra sintaxis que no plantea ningún problema a la hora de traducir la sentencia original como se muestra a continuación:

Sintaxis Informix-SQL: CREATE TEMP TABLE tablatemporal

Sintaxis de SqlServer: CRETE TABLE #tablatemporal

Page 117: IfxToJava2

117

Sintaxis de Oracle: CREATE GLOBAL TEMPORARY TABLE tablatemporal

Sintaxis de DB2: DECLARE GLOBAL TERMPORARY TABLE tablatemporal

La sintaxis que hay hasta el nombre de la tabla temporal es estática con lo cual en el momento que aparece el nombre de la tabla, a la hora de analizar el código fuente, se genera una sentencia u otra en función del gestor de base de datos destino.

Tanto en la definición de restricciones de tabla como de columna no contempla la posibilidad de asociarles un nombre lo que implica que la definición sintáctica de restricciones es equivalente para todos los gestores de bases de datos aquí estudiados.

La opción �in CAMINO� es igual en la sentencia: CREATE TEMP TABLE que en: CREATE TABLE. La solución será la misma, que la planteada en este Último caso. Si se está generando código para Informix-SQL se atenderá a la variable de entorno DBPATH en lugar de DBTEMP.

En cuanto al problema planteado con el gestor de bases de datos oracle se proponen varias soluciones:

Mantener en una estructura, en tiempo de ejecución, la relación de las tablas temporales creadas y al salir del programa principal eliminarlas. Esto no es tan fácil, puesto que Informix es un lenguaje de programación multimódulo y habría que mantener la relación de tablas temporales de cada módulo para luego eliminarlas en el módulo principal.

No mantener ninguna estructura y cuando se vaya a crear una tabla temporal borrarla primero teniendo en cuenta que en caso de que no exista dicha tabla temporal no se genere ningún error. Esta solución no es muy limpia puesto que siempre se mantendrán las tablas temporales como parte de la base de datos.

La última solución propuesta es generar la tabla temporal controlando que en caso de que ya exista no se genere ningún error. Esta solución es equivalente a la anterior pero no contempla el caso de que el esquema de la tabla temporal ya definida no coincida con la que el programa en curso trata de crear.

La solución que se va a adoptar para el caso de las tablas temporales de Oracle es la segunda de las propuestas puesto que ofreciendo todas las misma funcionalidad es las más simple de implementar manteniendo la última estructura de tabla.

Como se comento al definir la sintaxis de SqlServer sino se indica explícitamente el usuario por defecto toma como usuario de creación de la tabla el usuario dbo, y esto puede dar problemas al traducir otras sentencias que en el cuerpo de la misma indiquen el usuario, ejemplo: select usuario.tabla.campo from ..... Para evitar esto a la hora de pasar el código fuente a un código objeto ejecutable sobre SqlServer se especificará el propietario de la tabla, el cual se puede obtener de la cadena de conexión contra la base de datos. El resto de gestores de bases de datos crean la tabla con el propietario igual al usuario que esta conectado a la base de datos.

En el caso de Db2 si en la definición original de la tabla temporal hay restricciones estas no se generarán en el código objeto. Este hecho se notificará en tiempo de traducción mediante un Warning.

Un aspecto que hasta ahora no se ha tenido en cuenta y que empieza a tener relevancia es la definición de tipos de datos en los distingos gestores de bases de datos estudiados. Este punto lleva un estudio detallado el cual se realiza en el apartado: Tipos de datos (ver página 154)

En el Anexo I, apartado: Ejemplo sentencias creacion tabla temporal, se muestran ejemplos del uso de esta sentencia.

SENTENCIA CREATE VIEW

Crea una tabla virtual que representa los datos de una o más tablas de una forma alternativa. Las vistas se pueden utilizar como mecanismos de seguridad al conceder permisos sobre una vista, pero no sobre las tablas subyacentes (base).

Esta sentencia es soportada por el estándar SQL92, y todos los gestores de bases de datos aquí estudiados se ajustan al estándar SQL92 y en algunos casos lo extienden.

Page 118: IfxToJava2

118

Informix-SQL se ajusta completamente al estándar, la única limitación podría venir dada por la definición de la sentencia SELECT la cual es estudia más adelante al analizar dicha sentencia (ver página 143).

SINTAXIS DE INFORMIX

<CREATEVIEW> ::= CREATE VIEW nombrevista [ ( nombrecolumna [,...n] ) ] AS <sentenciaselect> [ WITH CHECK OPTION ]

La opción WITCH CHECK OPTION indica al gestor de base de datos que cualquier modificación hecha a través de la vista en la/s tabla/s o vista/s en las cual se basa ésta deben de cumplir las condiciones indicadas en la definición de la misma (sentencia select).

SINTAXIS DE SQLSERVER

<CREATEVIEW> ::= CREATE VIEW nombrevista [ ( nombrecolumna [,�n]) ] [WITH ENCRYPTION] AS <sentenciaselect> [WITH CHECK OPTION]

SINTAXIS DE ORACLE

<CREATEVIEW> ::= CREATE [OR REPLACE] VIEW [<esquema>] nombrevista [ ( nombrecolumna [,...n] ) ] AS <sentenciaselect> [ WITH [ READ ONLY | CHECK OPTION [ CONSTRAINT nombrerestriccion ] ]

SINTAXIS DE DB2

<CREATEVIEW> ::= CREATE [FEDERATED] VIEW nombrevista [ ( nombrecolumna [,...n] ) ] AS [ WITH {<expresion comun> [,�n]} | <sentenciaselect> ] [ WITH [ <cláusula levels> ] CHECK OPTION ] <cláusula levels> ::= CASCADED | LOCAL <expresión común> ::= nombretabla [ ( nombrecolumna [,�n] ) ] AS ( <sentenciaselect> )

GENERACIÓN DE CODIGO

La generación de código no plantea ningún problema puesto que la sentencia original de Informix-SQL es soportada en su totalidad e interpretada de igual forma por el resto de gestores de bases de datos.

Al igual que ocurría con la sentencia CREATE SYNONYM (ver página 111) hay que tener en cuenta que la sentencia DROP TABLE (ver página 124) se comporta de forma distinta en el resto de gestores de bases de datos. En ese caso la solución adoptada es la misma, si el gestor destino no es Informix-SQL se borraran primero las vistas antes de crearlas evitando así errores en tiempo de ejecución.

Para ver un caso practico del comportamiento del traductor con esta sentencia dirigirse al punto: Ejemplo sentencia creacion vista, dentro del Anexo I.

SENTENCIA DATABASE

La sentencia DATABASE permite seleccionar una base de datos accesible como la base de datos actual.

Esta sentencia no es soportada por el estándar SQL89 y tampoco por el SQL92 y es una ampliación que Informix-SQL añade a su versión 4.10.

El estándar SQL92 y el resto de gestores de bases de datos contemplan la sentencia CONNECT que permite establecer una conexión con una base de datos del gestor de bases de datos.

Page 119: IfxToJava2

119

Los comandos: DATABASE, CREATE DATABASE, START DATABASE, y CONNECT TO database provocan un conexión con la base de datos referenciada en los mismos.

SINTAXIS INFORMIX

<DATABASE> ::= DATABASE <nombrebasedatos> [EXCLUSIVE] <nombrebasedatos> ::= nombrebasedatos | �espcificacionbd� | < variable>

Esta sentencia indica, a partir del punto donde aparece, la base de datos sobre la cual se ejecutan el resto de sentencias SQL del programa.

EXCLUSIVE indica que la base de datos se abre en modo exclusivo y evita que cualquier otro usuario pueda acceder a la misma.

GENERACIÓN DE CODIGO

Dado que el código que se genera es JAVA, el cual permite establecer conexiones con las bases de datos, que no existe una traducción directa de la sentencia original al resto de gestores de bases de datos y que todo gestor de bases de datos permite especificar, de una forma u otra, la base de datos con la cual se esta trabajando se interpretará esta sentencia como el abrir una conexión con la base de datos que recibe como parámetro. En el caso de que ya hubiese una conexión establecida se cerrará previamente esta.

En los Fuentes mostrados en el Anexo I: Ejemplo sentencias conexión/desconexión, se puede ver un ejemplo práctico del uso de esta sentencia.

Si se observa el código objeto generado se puede ver que no se hace referencia directamente a la clase java.sql.Connection. Las funciones de conexión a la base de datos están definidas en una clase propia llamada: AccesDB y dentro de ésta, para reflejar la sentencia DATABASE se han defino las siguiente sentencias:

static AccesDB ASGdb = null, definición de una variable de la clase AccesDB.

new AccesDB("datos") se encarga de establecer la conexión por primera vez a la base de datos al tiempo que inicializa la clase.

SENTENCIA DECLARE CURSOR

Esta sentencia permite definir un cursor el cual representa un conjunto activo de filas indicadas a través de una sentencia SELECT.

SINTAXIS DE INFORMIX

<DECLARECURSOR> ::= DECLARE nombrecursor [SCROLL] CURSOR [WITH HOLD] FOR [ <senteniaselect> [<opcforupdate>] | <sentenciainsert> | <variablesentenciapreparada> ]

<opcforupdate> ::= FOR UPDATE [OF nombrecolumna [, ..n]]

La opción SCROLL CURSOR indica que si durante el tiempo que se esta procesando las filas del cursor otro usuario modifica los datos de la tabla afectada por el cursor estas modificaciones no serán visibles por el primero. Informix, si se usa esta opción, hace un recorrido inicial de las tablas afectadas en la <sentenciaselect> y los carga en una tabla temporal, tabla con la cual trabaja durante el procesamiento del cursor.

La opción WITH HOLD permite un acceso ininterrumpido al conjunto de filas durante múltiples transacciones. Normalmente todos los cursores son cerrados al final de una transacción.

La cláusula FOR UPDATE indica al gestor de bases de datos que es posible se modifiquen datos durante el recorrido del cursor. Para modificar los datos se puede utilizar la sentencia UPDATE o DELETE con la cláusula: WHERE CURRENT OF, que indica la fila actual.

Page 120: IfxToJava2

120

SINTAXIS DE SQLSERVER

<DECLARECURSOR> ::= DECLARE nombrecursor CURSOR [LOCAL | GLOBAL] [FORWARD_ONLY | SCROLL] [STATIC | KEYSET | DYNAMIC | FAST_FORWARD] [READ_ONLY | SCROLL_LOCKS | OPTIMISTIC] [TYPE_WARNING] FOR <sentenciaselect> [FOR UPDATE [OF nombrecolumna [,...n]] ]

SINTAXIS DE ORACLE

<DECLARECURSOR> ::= DECLARE CURSOR nombrecursor IS <sentenciaselect>

SINTAXIS DE DB2

<DECLARECURSOR> ::= DECLARE nombrecursor CURSOR [WITH HOLD] FOR [ <sentenciaselect> | <variablesentenciapreparada> ]

GENERACIÓN DE CÓDIGO

Como se ve al analizar la sintaxis del resto de gestores no todos ellos definen la sentencia al igual que lo hace Informix-SQL, esto no será relevante ya que la traducción a código objeto de la misma se realizará basándose en las sentencias que proporciona el API JDBC de JAVA para el manejo de cursores.

A la hora de generar código se entenderá que todas las sentencias utilizan la opción WITH HOLD aunque en código fuente no se utilice. Esto se hace así debido a que partimos de un gestor de bases de datos no transaccional y pasamos a otros que normalmente lo son y para los cuales por defecto las sentencias son autoentregables (una sentencia una transacción).

En la sección: Sentencias de manipulación dinámica de datos y cursores se mostrarán ejemplos de esta sentencia, junto con el resto de sentencias de manejo de cursores, así como las peculiaridades de su traducción a código objeto.

SENTENCIA DELETE FROM

Esta sentencia permite eliminar filas de una tabla determinada de la base de datos. Los datos borrados se establecen según el criterio:

En función del criterio de búsqueda especificado en la condición.

La fila actualmente posicionada por un cursor.

Esta sentencia según la específica Informix-SQL es soportada en su totalidad por el estándar SQL92.

SINTAXIS DE INFORMIX

<DELETEFROM> ::= DELETE FROM <elementoaborrar> [ <restosentdeletefrom> ] <elementoaborrar> ::= nombretabla | nombresinonimo | nombrevista <restosentdeletefrom> ::= WHERE [ <condicionsql> | CURRENT OF nombrecursor ]

Page 121: IfxToJava2

121

SINTAXIS DE SQLSERVER

<DELETEFROM> ::= DELETE [FROM] <elementoaborrar> [ <restosentdeletefrom> ] <elementoaborrar> ::= nombretabla | nombrevista | nombresinonimo <restosentdeletefrom> ::= WHERE [ CURRENT OF nombrecursor | <condicionsql> ]

SINTAXIS DE ORACLE

<DELETEFROM> ::= DELETE [FROM] <elementoaborrar> [ <restosentdeletefrom> ] <elementoaborrar> ::= nombretabla | nombrevista | nombresinonimo <restosentdeletefrom> ::= WHERE [ CURRENT OF nombrecursor | <condicionsql> ]

SINTAXIS DE DB2

<DELETEFROM> ::= DELETE [FROM] <elementoaborrar> [ <restosentdeletefrom> ] <elementoaborrar> ::= nombretabla | nombrevista | nombresinonimo <restosentdeletefrom> ::= WHERE [ CURRENT OF nombrecursor | <condicionsql> ]

GENERACIÓN DE CÓDIGO

La traducción de esta sentencia de código fuente, Informix-SQL, a código objeto, java, no platea ningún problema ya que dicho código objeto será el mismo independientemente del gestor para el cual estemos generando código.

En esta sentencia aparece un elemento que debe de ser estudiado con detenimiento para garantizar que la sentencia sea ejecutada con éxito en cualquier gestor de bases de datos, este elemento es la condicionsql la cual será analizada en detalle en el apartado: Operaciones sobre expresiones sql.

En el Anexo I, apartado: Ejemplo sentencia delete se muestra ejemplo de la traducción de esta sentencia.

Aquí no se contemplo la generación de código para la cláusula: WHERE CURRENT OF, esta se analizará en la sección: Sentencias de manipulación dinámica de datos y cursores.

SENTENCIA DROP AUDIT FOR

Esta sentencia permite detener y borrar la generación de un log para una tabla o vista de la base de datos.

Al igual que ocurría en la sentencia: CREATE AUDIT (ver página 106) y por los mismos motivos citados no se traducirá este código java.

SINTAXIS DE INFORMIX

<DROPAUDITFOR> ::= DROP AUDIT FOR [ nombretabla | nombresinonimo ]

Page 122: IfxToJava2

122

SENTENCIA DROP DATABASE

Permite eliminar una base de datos completa incluyendo todas las tablas del catalogo, índices y datos.

Esta sentencia no es contemplada por el estándar SQL89, Informix-SQL lo amplia al usarla, tampoco es soportada por el SQL92 aunque de una forma u otra todo gestor de bases de datos la implementa.

SINTAXIS DE INFORMIX

<DROPDATABASE> ::= DROP DATABASE <nombrebasedatos> <nombrebasedatos> ::= nombrebasedatos | �espcificacionbd� | <variable>

SINTAXIS DE SQLSERVER

<DROPDATABASE> ::= DROP DATABASE nombrebasedatos [,...n ]

SINTAXIS DE ORACLE

<DROPDATABASE> ::= DROP DATABASE nombrebasedatos

SINTAXIS DE DB2

<DROPDATABASE> ::= DROP [ DATABASE | DB ] nombrebasedatos [ AT NODE ]

GENERACIÓN DE CÓDIGO

Esta es una sentencia de administración que rara vez se ejecuta desde un programa, siempre se crean y borran las bases de datos a través de la herramienta de administración proporcionada por cada gestor de bases de datos. Aun así se incorporara la traducción de la misma a código objeto puesto que su traducción no plantea ningún problema.

La traducción a java del código fuente es directa puesto que, aunque el resto de gestores admite más posibilidades, soportan sin ninguna limitación la sintaxis original de Informix-SQL.

SENTENCIA DROP INDEX

La sentencia DROP INDEX permite eliminar un índice de la base de datos. El usuario que borra el índice debe de ser propietario del mismo o tener privilegios de DBA.

El estándar SQL92 no la contempla, Informix-SQL la incorpora como una ampliación en su versión 4.10. El resto de gestores también proporciona una sentencia que permite borrar índices de la base de datos.

SINTAXIS DE INFORMIX

<DROPINDEX> ::= DROP INDEX nombreindice

SINTAXIS DE SQLSERVER

<DROPINDEX> ::= DROP INDEX { tabla.nombreindice | vista.nombreindice } [ ,...n ]

Page 123: IfxToJava2

123

SINTAXIS DE ORACLE

<DROPINDEX> ::= DROP INDEX [ <esquema> . ] nombreindice

SINTAXIS DE DB2

<DROPINDEX> ::= DROP INDEX nombreindice

GENERACIÓN DE CÓDIGO

Como se observa en la definición de la sentencia por los distintos gestores de bases de datos y la sentencia definida por Informix-SQL, ésta es admitida sin ninguna limitación. Aún así SQLSERVER exige que se especifique la tabla de la cual se va a borrar el índice.

Para todos los gestores, exceptuando SQLSERVER, se transcribe la sentencia original según aparece en el código fuente. Para el caso de SQLSERVER es preciso localizar la tabla (o vista) de la cual se trata de borrar el índice, para ello se lanzará la siguiente sentencia al gestor de bases de datos:

select name from sys.tables where object_id = ( select object_id from sys.indexes where name = 'indice1')

Una vez obtenido el nombre de la tabla (o vista) se concatenará este con el nombre del índice y se lanzará la sentencia contra el gestor de bases de datos. Tener en cuenta que este dato se ha de obtener en tiempo de ejecución, ya que en tiempo de compilación puede aún no existen la tabla o vista en la base de datos.

El único problema que plantearía esta búsqueda es que hubiera dos índices nombrados igual aunque sobre distinta tabla. Esto no se producía ya que el gestor de bases de datos original no lo permite y se entiende que los programas lanzados sobre el gestor de bases de datos destino fueron diseñados para Informix-SQL.

Dentro del Anexo I, en el epígrafe: Ejemplo sentencia drop index, se muestra caso práctico de la traducción de esta sentencia para cada gestor de bases datos.

SENTENCIA DROP SYNONYM

Esta sentencia permite borrar un sinónimo de la base de datos.

El estándar SQL89 no la contempla y tampoco el SQL92, Informix-SQL la soporta como una aplicación al estándar. Todos los gestores de bases de datos aquí estudiados soportan esta sentencia.

SINTAXIS DE INFORMIX

<DROPSYNONYM> ::= DROP SYNONYM nombresinonimo

SINTAXIS DE ORACLE

<DROPSYNONYM> ::= DROP [ PUBLIC ] SYNONYM [ <esquema> ] nombresinonimo

SINTAXIS DE DB2

<DROPSYNONYM> ::= DROP ALIAS nombresinonimo

Page 124: IfxToJava2

124

GENERACIÓN DE CÓDIGO

Para todos los gestores de base de datos la traducción de la sentencia original de Informix-SQL no plantea ningún problema aunque habrá que atender a la sintaxis de esta para cada gestor de bases de datos.

Dentro del Anexo I, en el apartado: Ejemplo sentencia drop, se muestra caso práctico de la traducción de esta sentencia para cada uno de los gestores de bases de datos estudiados.

SENTENCIA DROP TABLE

Esta sentencia permite eliminar una tabla de la base de datos junto con sus índices, restricciones y datos asociados. También son eliminados todos los sinónimos, triggers y vistas asociados a la tabla. No son eliminados los sinónimos creados en bases de datos externas.

Esta sentencia se ajusta al estándar SQL92, aunque éste tiene una sintaxis más amplia.

SINTAXIS DE INFORMIX

<DROPTABLE> ::= DROP TABLE nombretabla

SINTAXIS DE SQLSERVER

<DROPTABLE> ::= DROP TABLE nombretabla

SINTAXIS DE ORACLE

<DROPTABLE> ::= DROP TABLE [<esquema>] nombretabla [ CASCASDE CONSTRAINT ]

La opción CASCADE CONSTRAINTS aplica la integridad referencial y borra todos los constraints que hacen referencia a las claves primarias y claves únicas de la tabla que se borra.

SINTAXIS DE DB2

<DROPTABLE> ::= DROP TABLE nombretabla

GENERACIÓN DE CÓDIGO

La generación de código no plantea ningún problema puesto que la sintaxis de la sentencia original de Informix-SQL es plenamente soportada por el resto de gestores de bases de datos.

El eliminar una tabla de la base de datos para Informix-SQL significa que se eliminan todos los sinónimos, triggers y vistas creados sobre ella, sin embargo para el resto de los gestores estos persisten. Esta distinta interpretación de la sentencia DROP TABLE para el resto gestores trae el problema de que en ellos se puede estar intentando crear una vista, sinónimo o trigger que ya existe. En el ejemplo siguiente se muestra el problema:

Sentencia:

create table tabla1; create table tabla2; create view vista1 on select * from tabla1; drop table tabla1; create view vista1 on select * from tabla2;

En este ejemplo funcionaría sin ningún problema para el Informix-SQL, para el cual se escribió la misma, sin embargo para el resto de gestores, sobre el que se trata se pueda ejecutar, daría un error puesto que en ellos la vista: vista1 aún existe. En el momento donde se analizó cada una de las sentencias CREATE se propusieron soluciones para evitar la persistencia de las vistas y sinónimos tras la desaparición de la tabla en el resto de gestores de bases de datos.

Page 125: IfxToJava2

125

Dentro del Anexo I, en el apartado: Ejemplo sentencia drop, se muestra caso práctico de la traducción de esta sentencia para cada uno de los gestores de bases de datos estudiados.

SENTENCIA DROP VIEW

Esta sentencia permite borrar una vista de la base de datos.

La sentencia es contemplada por el estándar SQL92 y lo hace de una forma más amplia que Informix-SQL pero cubriendo la sintaxis de éste por completo.

SINTAXIS DE INFORMIX

<DROPTABLE> ::= DROP VIEW nombrevista

SINTAXIS DE SQLSERVER

<DROPVIEW> ::= DROP VIEW nombrevista [,�n]

SINTAXIS DE ORACLE

<DROPVIEW> ::= DROP VIEW [<esquema>] nombrevista

SINTAXIS DE DB2

<DROPVIEW> ::= DROP VIEW nombrevista

GENERACIÓN DE CÓDIGO

Al igual que ocurría con la sentencia DROP TABLE la sentencia original de Informix-SQL se puede ejecutar, sin ninguna modificación, sobre cualquier gestor de bases de datos.

En los ejemplos mostrados en el cuadro anterior, Sentencia DROP TABLE, se puede ver también el uso de esta sentencia.

SENTENCIA EXECUTE

Esta sentencia permite ejecutar una sentencia o conjunto de sentencias previamente preparadas. Su utilización esta siempre ligado al uso de la sentencia PREPARE.

SINTAXIS DE INFORMIX

<EXECUTE> ::= EXECUTE nombresentenciapreparada [ USING <variable> [,�n] ]

La cláusula USING especifica los valores que reemplazarán el símbolo �?� dentro de la sentencia preparada. El siguiente ejemplo de código fuente permitirá aclarar el funcionamiento de esta sentencia:

LET stm_1 = "UPDATE orders SET order_date = ? WHERE po_num = ?"

PREPARE statement_1 FROM stm_1

EXECUTE statement_1 USING x_o_date, x_po_num

SINTAXIS DE SQLSERVER

<EXECUTE> ::= EXECUTE nombresentenciapreparada [USING DESCRIPTOR <estructuradevariables> | USING <variable> [,...]]

Page 126: IfxToJava2

126

SINTAXIS DE ORACLE

<EXECUTE> ::=

EXECUTE nombre_sentencia [ USING variable [, �n] ]

SINTAXIS DE DB2

<EXECUTE> ::= EXECUTE nombresentenciapreparada [ INTO variableresulado [, �n] | DESCRIPTOR nombredescriptor ] [ USING variable [, �n] | DESCRIPTOR nombredescriptor ]

GENERACION DE CÓDIGO

Esta sentencia aunque es soportada por todos los gestores, junto con la sentencia PREPARE, tendrá una traducción más compatible con todos ellos utilizando las �sentencias preparadas� del JDBC de JAVA. Ver el siguiente ejemplo:

integer campo;

PreparedStatement x = conn.prepareStatement ("insert into tabla values(?)");

x.setInt(1, campo);

x.executeUpdate();

Así la sentencia PREPARE de Informix-SQL se traducirá a prepareStatement del JDBC de JAVA y la EXECUTE a una combinación de las sentencias setXXXX para realizar la parte USING, y executeUpdate para realizar el EXECUTE propiamente dicho. Véase dentro del Anexo I los ejemplos prácticos de traducción de código fuente a código objeto ejecutable sobre cada gestor en el punto: Ejemplo sentencia prepare/execute � prepare/declare.

A la hora de fijar los valores de las sentencia SQL se utilizan variables de programa, en función del tipo de estas se utilizará una función setXXXX u otra.

SENTENCIA FETCH

Esta sentencia se utiliza para posicionar el cursor dentro del conjunto en curso y para retornar los valores de la posición indicada en la memoria para ser usados por el programa.

SINTAXIS DE INFORMIX

<FETCH> ::= FETCH [ <fetch orientacion> ] nombredecursor INTO <lista de variables> <fetch orientacion> ::= NEXT | PRIOR | PREVIOUS | FIRST | LAST | CURRENT | { ABSOLUTE | RELATIVE } <especificación de valor> <especificación de valor> ::= nombredevariable | númerodefila <lista de variables> ::= nombredevariable [ nombredevariable [,�n] ]

Devuelve los valores de un conjunto activo y especifica las variables en las que se guardara el resultado. El cursor ha debido ser previamente declarado y abierto.

Page 127: IfxToJava2

127

SINTAXIS DE SQLSERVER

<FETCH> ::= FETCH [ [ NEXT | PRIOR | FIRST | LAST | ABSOLUTE { númerofila | nombrevariable } | RELATIVE { númerofila | nombrevariable } ] FROM ] { { [ GLOBAL ] nombrecursor } | nombredevariable_cursor } [ INTO nombredevariable [ ,�n ] ]

Como se ve esta sentencia es totalmente compatible con la de Informix-SQL, puesto que PRIOR es equivalente PREVIOUS y CURRENT es lo mismo a no poner nada.

SINTAXIS DE ORACLE

<FETCH> ::= FETCH nombredecursor [ INTO <variable> [,�n] | USING DESCRIPTOR nombredescriptor ]

Esta sentencia retorna las filas del conjunto de resultados una de cada vez. Cada FETCH retorna la fila actual y avanza el cursor a la fila siguiente dentro del conjunto de resultados.

SINTASIX DE DB2

<FETCH> ::= FETCH [ FROM ] nombredecursor [ INTO <variable> [,�n] | USING DESCRIPTOR nombredescriptor ]

Al igual que la sentencia proporcionada por Oracle ésta no soporta la ubicación relativa del cursor, siempre retornara el siguiente.

GENERACIÓN DE CÓDIGO

Al igual que para con el resto de sentencias de manejo de cursores no será importante que la sintaxis original de Informix-SQL no sea soportada por el resto ya que se utilizarán la funciones estándar del JDBC de JAVA para realizar la traducción de código fuente a código objeto.

La generación de código de esta sentencia se verá en el apartado: Sentencias de manipulación dinámica de datos y cursores

SETENCIA FLUSH

Esta sentencia fuerza que las filas que fueron puestas en memoria por la sentencia PUT pasen a la base de datos.

<FLUSH> ::= FLUSH nombre_cursor

El conjunto PUT/FLUSH hace el mismo trabajo que la sentencia FETCH. Si se finaliza el programa sin hacer un FLUSH o en su defecto cerrar el cursor los datos puestos en memoria se pierden sin ser pasados a base de datos. Ejemplo:

DECLARE c1 CURSOR FOR

INSERT INTO tabla1 VALUES (código, nombre) OPEN c1 LET code = "AS" LET sname = "Asturias" PUT c1 FLUSH c1 CLOSE c1

La transformación de esta sentencia sería:

Page 128: IfxToJava2

128

PREPARE s1 FROM �INSERT INTO tabla1 VALUES (?,?) DECLARE c1 for s1 OPEN c1 LET code = "AS" LET sname = "Asturias" PUT c1 FROM code, sname FLUSH c1 CLOSE c1

El conjunto de sentencias FLUSH/FREE/PUT no es soportada por ninguno de los otros gestores de bases de datos estudiado pero, al igual que con el resto de sentencias de manejo de cursores, esto no plantea problema ya que generará código objeto utilizando los métodos estándar del JDBC de JAVA soportados por cada proveedor de bases de datos.

SENTENCIA FREE

Esta sentencia libera los recursos que están reservados para una sentencia preparada o un cursor.

SENTENCIA FREE

<FREE> ::= FREE nombre_cursor

SENTENCIA GRANT

Esta sentencia permite:

Autorizar a otros usuarios distintos del creador de la base de datos a: usarla, desarrollar sobre ella, o administrarla.

Posibilitar a otros usuarios distintos del creador ver, alterar o eliminar una tabla, vista o sinónimo.

El estándar SQL92 contempla esta sentencia aunque la versión de ella que define Informix-SQL no se ajusta al mismo en varios aspectos. El estándar solo contempla en esta sentencia el dar permisos sobre objetos de la base de datos.

SINTAXIS DE INFORMIX

<GRANT>::= GRANT <PRIVILEGIOS> TO [ PUBLIC | usuario[, ...n] ] <PRIVILEGIOS> ::= <PRIVILEGIOSDEBASEDEDATOS> | <PRIVILEGIOSDETABLAS> <PRIVILEGIOSDEBASEDEDATOS> ::= CONNECT | RESOURCE | DBA <PRIVILEGIOSDETABLAS> ::= { ALL [PRIVILEGES] | <PRIVILEGIOSTABLA> [, ...n] } ON [TABLE] { nombretabla | nombrevista | nombresinonimo } <PRIVILEGIOSTABLA> ::= INSERT | DELETE | SELECT [ ( nombrecolumna [, ...n] ) ] | UPDATE [ ( nombrecolumna [, ...n] ) ] | ALTER | INDEX

Los permisos sobre la base de datos son:

Page 129: IfxToJava2

129

CONNECT. Un usuario con este tipo de privilegios puede realizar las siguientes tareas:

Establecer una conexión a la base de datos.

Ejecutar sentencias SELECT, UPDATE, INSERT, y DELETE sobre tablas en las cuales el usuario tenga suficientes privilegios.

Crear vistas sobre tablas sobre las que el usuario tenga suficientes privilegios.

Crear sinónimos.

Crear tablas temporales y crear índices sobre las tablas temporales.

RESOURCE. Proporciona la posibilidad de variar la estructura de la base de datos. Además de las tareas que puede realizar un usuario con privilegios Connect. Un usuario que posee en nivel de privilegios Resource puede realizar:

Crear nuevas tablas.

Crear nuevos índices.

Crear nuevas rutinas.

Crear nuevas bases de datos.

DBA. Tiene todas las capacidades del privilegio Resource y además la posibilidad de:

Dar cualquier privilegio a nivel de bases de datos incluso el DBA sobre cualquier usuario.

Dar cualquier privilegio a nivel de tabla sobre cualquier usuario.

Quitar privilegios sobre cualquier objeto independientemente de que sea o no suyo.

Crear tablas, vistas, o índices e indicar como propietario a otro usuario.

Ejecutar la sentencia DROP DATABASE.

insertar, modificar o borrar filas sobre cualquier tabla del sistema a excepción de systables, sobre esta solo puede actuar el usuario informix.

Los permisos sobre tablas son:

INSERT. Permite al poseedor de este privilegio insertar filas en la tabla, vista, o sinónimo.

DELETE. Permite al poseedor de este privilegio eliminar filas de la tabla, vista, o sinónimo.

SELECT. El usuario con este privilegio puede seleccionar y ver datos. Se puede limitar los columnas con este privilegio indicando en esta sentencia las columnas a las cuales puede acceder, sino se indica ninguna se entiende que tiene acceso a todas.

UPDATE. El poseedor de este privilegio puede modificar datos. Se puede especificar aquellas columnas sobre las cuales se tiene este privilegio.

INDEX. Permite al poseedor de este privilegio el crear índices permanentes sobre una tabla. Este privilegio no tendrá efecto a menos que el usuario posea también privilegios Resource sobre la base de datos.

ALTER. Permite al usuario realizar todas las funciones proporcionadas por la sentencia ALTER TABLE. Este privilegio no tendrá efecto a menos que el poseedor de este privilegio posea también el privilegio a nivel de bases de datos: Resource.

SINTAXIS DE SQLSERVER

<GRANT> ::= GRANT {ALL | instrucción[,�n]} TO cuentaseguridad[,�n] | GRANT

Page 130: IfxToJava2

130

{ALL [PRIVILEGES] | <permiso>[,�n]} { [(columna[,�n])] ON {tabla | vista} | ON {tabla | vista}[(columna[,�n])] | ON {procedimientoalmacenado | procedimientoextendido} } TO cuentaseguridad[,�n] [WITH GRANT OPTION] [AS {grupo | función}] <permiso> ::= INSERT | UPDATE | SELECT | DELETE | ALTER | REFERENCES | EXECUTE

Con esta sentencia se permite a un usuario de la base de datos actual trabajar con datos de la base de datos actual (permisos de objeto) o ejecutar instrucciones SQL específicas (permisos de la instrucción).

Es la instrucción para la que se concede el permiso. La lista de instrucciones puede contener:

CREATE DATABASE

CREATE DEFAULT

CREATE PROCEDURE

CREATE RULE

CREATE TABLE

CREATE VIEW

BACKUP DATABASE

BACKUP LOG

Las instrucciones que requieren permisos son las que agregan objetos a la base de datos o realizan actividades administrativas en ella. Cada instrucción que requiere permisos tiene un conjunto de funciones determinado que automáticamente tiene permiso para ejecutarla. Por ejemplo, de forma predeterminada tienen permiso sobre CREATE TABLE los miembros de las funciones sysadmin, db_owner y db_ddladmin. De forma predeterminada, tienen permisos para ejecutar la instrucción SELECT en una tabla las funciones sysadmin y db_owner, y también el propietario del objeto.

Cada objeto de una base de datos de SQLSERVER tiene un propietario, normalmente el identificador del usuario activo en la conexión en que se creó el objeto. Otros usuarios no pueden tener acceso a ese objeto hasta que el propietario autorice a sus identificadores de usuario para que tengan acceso al objeto.

Ciertas instrucciones de SQL también están limitadas a determinados identificadores de usuario. Por ejemplo, la instrucción CREATE DATABASE está limitada a los miembros de las funciones fijas de servidor sysadmin y dbcreator.

Los permisos que se pueden conceder a los objetos son:

SELECT. Permite a un usuario emitir instrucciones SELECT en una tabla o vista.

INSERT. Permite a un usuario emitir instrucciones INSERT en una tabla o vista.

UPDATE. Permite a un usuario emitir instrucciones UPDATE en una tabla o vista.

Page 131: IfxToJava2

131

DELETE. Permite a un usuario emitir instrucciones DELETE en una tabla o vista.

REFERENCES. Permite a un usuario insertar una fila en una tabla que tiene una clave externa, que hace referencia a la tabla que se nombra en la instrucción GRANT, DENY y REVOKE.

EXECUTE. Permite a un usuario emitir instrucciones EXECUTE en un procedimiento almacenado.

La cláusula: WITH GRANT OPTION específica que se concede a cuentaseguridad la capacidad de conceder el permiso de objeto especificado a otras cuentas de seguridad. La cláusula WITH GRANT OPTION sólo es válida con los permisos de objeto.

SINTAXIS DE ORACLE

<GRANT>::= { GRANT <PRIVILEGIOS> ON <OBJETOS> TO <USUARIOS> | GRANT <ROLL> TO <USUARIOS> } [ WITH GRANT OPTION ] <PRIVILEGIOS> ::= { {ALL PRIVILEGES | <PRIVILETIODEOBJETO> } [ ( nombrecolumna [, ...n]) ] } [, ...n] <PRIVILEGIOSDEOBJETO> ::= ALL | ALTER | DELETE | INDEX | INSERT | SELECT | UPDATE | REFERENCES <USUARIOS> ::= PUBLIC | usuario[, ...n] <OBJETOS> ::= { tabla | vista | sinónimo | ... } [ ...n] <ROLL> ::= { ADMIN | DLL }

Para conceder roles a usuarios el que lo concede debe haber iniciado sesión en la base de datos como SYSTEM o bien como un usuario con privilegios DLL o ADMIN.

El rol ADMIN posibilita al usuario que lo tiene crear otros usuarios y concederles permisos sobre cualquier objeto de la base de datos. El usuario puede ejecutar los siguientes comandos: CREATE SCHEMA, CREATE USER, ALTER USER, DROP, USER, DROP SCHEMA, GRANT, y REVOKE.

El rol DDL habilita al usuario a ejecutar las siguientes sentencias: CREATE TABLE, CREATE VIEW, CREATE INDEX, CREATE CONSTRAINTS, ALTER TABLE, ALTER VIEW, ALTER INDEX, ALTER CONSTRAINT, DROP TABLE, DROP VIEW, DROP INDEX, y DROP CONSTRAINT.

Si al especificar los privilegios sobre objetos concedidos a un usuario se pone ALL el usuario podrá: alterar la estructura, crear índices, crear restricciones y ejecutar las sentencias: DELETE, INSERT, SELECT, UPDATE sobre el objeto.

SINTAXIS DE DB2

<GRANT>::= GRANT <PRIVILEGIOS> TO [ PUBLIC | [ USER | GROUP ] idusuariogrupo[, ...n] ] [WITH GRANT OPTION] <PRIVILEGIOS> ::= <PRIVILEGIOSDEBASEDEDATOS> | <PRIVILEGIOSDETABLAS>

Page 132: IfxToJava2

132

<PRIVILEGIOSDEBASEDEDATOS> ::= { CONNECT | CREATETABLE | CREATE_NOT_FENCED | BINDADD | IMPLICIT_SCHEMA | BDADM | LOAD } ON DATABASE <PRIVILEGIOSDETABLAS> ::= { ALL [PRIVILEGES] | <PRIVILEGIOSTABLA> [, ...n] } ON [TABLE] { nombretabla | nombrevista | nombresinonimo } <PRIVILEGIOSTABLA> ::= INSERT | DELETE | CONTROL | SELECT [ ( nombrecolumna [, ...n] ) ] | REFERENCES [ ( nombrecolumna [, ...n] ) ] | UPDATE [ ( nombrecolumna [, ...n] ) ] | ALTER | INDEX

Permite conceder permisos a la base de datos por completo o bien sobre tablas o vistas.

Permisos sobre base de datos:

BDADM. Concede los permisos de administrador de la base de datos. El administrador de la base de datos tiene todos los privilegios sobre los objetos de la misma y puede conceder privilegios a otros usuarios.

BINDADD, CONNECT, CREATETAB, CREATE_NOT_FENCED e IMPLICIT_SCHEMA son automáticamente concedidos a un usuario que se le da el permiso DBADM.

IMPLICIT_SCHEMA. Concede permisos para crear schemas.

BINDADD. Concede permiso para crear paquetes.

CONNECT. Concede permiso de acceso a la base de datos.

CREATETAB. Concede permiso para crear tablas en la base de datos. El que crea la tabla adquiere automáticamente el privilegio CONTROL sobre la tabla el cual mantiene incluso si pierde el permiso CREATETAB.

CREATE_NOT_FENCED. Concede permisos para crear funciones que se ejecuten en la base de datos. Una vez que una función haya sido registrada esta continuará ejecutándose incluso si se pierde el privilegio CREATE_NOT_FENCED.

LOAD. Concede permiso para cargar datos en la base de datos. SYSADM y BDADM también tienen este permiso. Sin embargo, si un usuario carece de ellos deberá tener permisos a nivel de tabla: INSERT y DELETE.

Para conceder permisos de ejecución de sentencias sobre tablas o vistas se ha de tener sobre estas:

Privilegio de CONTROL.

Privilegios sobre ellas.

Autoridad de SYSADM o DBADM.

Para conceder el privilegio CONTROL se requiere autoridad de SYSADM o DBADM.

Page 133: IfxToJava2

133

Para conceder privilegios en tablas o vistas del catalogo se ha de poseer autoridad de SYSADM o DBADM.

Los permisos que se pueden conceder sobre tablas o vistas son:

ALTER. Concede permiso para:

Añadir columnas a una tabla de la base de datos.

Crear o eliminar claves primarias o restricciones únicas sobre las tablas.

Crear o eliminar claves ajenas sobre las tablas.

Crear triggers.

Crear check constraints.

CONTROL. Concede todos los privilegios necesarios para:

Ejecutar ALTER, CONTROL, DELETE, INSERT, INDEX, REFERENCES, SELECT, y UPTATE sobre tablas de la base de datos.

Permitir conceder los privilegios citados en el punto anterior, excepto CONTROL, a otros usuarios.

Ejecutar la sentencia DROP sobre tablas o vistas de la base de datos

DELETE. Concede privilegio para borrar filas de las tablas de la base de datos o actualizar vistas.

INDEX. Concede privilegio para crear índices sobre tablas.

INSERT. Concede el privilegio para inserta filas en tablas, actualizar vistas y ejecutar la utilidad IMPORT.

REFERENCES. Concede el privilegio para crear y eliminar claves ajenas.

SELECT. Concede privilegios para:

Retornar filas de una tabla o vista.

Crear vistas sobre una tabla.

Ejecutar la utilidad EXPORT a través de una tabla o vista.

UPDATE. Concede privilegio para ejecutar la sentencia UPDATE sobre una tabla o vista.

La opción: WITH GRANT OPTION de la sentencia GRANT posibilita a los usuarios que reciben un privilegio conceder este sobre otros usuarios.

GENERACIÓN DE CÓDIGO

La sentencia GRANT consta de dos subsentencias diferenciadas: una que da permisos sobre la base de datos, y otra que da permiso sobre tablas, vistas y/o sinónimos de la base de datos. En el caso de permisos sobre la base de datos las diferencias conceptuales entre la definición que aporta Informix-SQL y el resto de gestores de bases de datos hace su traducción prácticamente imposible. En el caso de concesión de permisos sobre tablas la interpretación de los distintos gestores es muy similar, conceder la ejecución de la sentencia a la que hace referencia, lo que facilitará su traducción a estos.

No hay que olvidar que la sentencia GRANT es una sentencia pura de administración y que es muy inusual que esta sentencia forme parte del código fuente de un programa de Informix-4GL . Lo más normal es ejecutar la sentencia en la herramienta de administración que proporciona cada gestor de bases de datos.

La solución planteada será no hacer será diferenciar la sentencia original en dos partes: una primera relativa a conceder permisos a nivel de base de datos y otra a nivel de objeto. En el

Page 134: IfxToJava2

134

primer caso si aparece en el código fuente, a la hora de procesar el código, se indicará por pantalla con el siguiente mensaje:

Línea: 4 Warning: Sentencia grant no generada

Para la concesión de permisos a nivel de objeto se generará código objeto sin limitaciones. En el apartado: Ejemplo sentencia grant, dentro del Anexo I se muestra un ejemplo del uso del traductor.

SENTENCIA INSERT INTO

Esta sentencia permite insertar filas en una tabla o vista.

Esta sentencia es soportada por el estándar SQL89 y por lo tanto también por el SQL92. Todos los gestores de bases de datos, aquí estudiados, la contemplan.

SINTAXIS DE INFORMIX

<SENTENCIAINSERT> ::= INSERT INTO { tabla | vista } [ ( <listacolumnas> ) ] <valoresdatos> <listacolumnas> ::= nombercolumna [,...n] <valoresdatos> ::= VALUES ( <valor> [,...] ) | <sentenciaselect> <valor> ::= <variable> | NULL | <expresioncte>

Esta sentencia permite una simple fila o un grupo de ellas si los datos son solucionados de otras tablas. Para insertar valores en una tabla se debe de ser propietario de la misma o tener privilegios de inserción sobre la misma.

SINTAXIS DE SQLSERVER

<SENTENCIAINSERT> ::= INSERT [INTO] {tabla | vista } [ ( <listacolumnas> ) ] <valoresdatos> <listacolumnas> ::= nombercolumna [,...n] <valoresdatos> ::= VALUES ( <expresión> [,...] ) | <sentenciaselect>

SINTAXIS DE ORACLE

<SENTENCIAINSERT> ::= INSERT INTO [ <esquema> ] { tabla | vista } [ ( <listacolumnas> ) ] <valoresdatos> <listacolumnas> ::= nombercolumna [,...n] <valoresdatos> ::= VALUES ( <expresión> [,...n] ) | <sentenciaselect>

SINTAXIS DE DB2

<SENTENCIAINSERT> ::= INSERT INTO { tabla | vista } [ ( <listacolumnas> ) ] <valoresdatos>

Page 135: IfxToJava2

135

<listacolumnas> ::= nombercolumna [,...n] <valoresdatos> ::= VALUES { ( <valor> [,...] ) | <valor> [,...] } | [ WITH <expresioncomun> [,...n] ] <sentenciaselect> <valor> ::= <expresión> | NULL | DEFAULT

GENERACIÓN DE CÓDIGO

La sentencia original de Informix-SQL se puede lanzar contra cualquier otro gestor de bases de datos, de los aquí estudiados, ya que su sintaxis es totalmente compatible. Los únicos puntos a considerar son: la compatibilidad de la sentencia SELECT con el resto de gestores de bases de datos la cual se tratara mas adelante (ver página 143), y la tolerancia de los valores de tipos de datos definidos por Informix-SQL por el resto de gestores (ver página 154).

En el Anexo I, punto: Ejemplo sentencia insert, se puede ver un caso del uso del traductor para esta sentencia.

SENTENCIA LOAD FROM

Esta sentencia permite cargar datos desde un fichero del sistema operativo en una tabla, vista o sinónimo de la base de datos.

Esta sentencia no es soportada por el estándar SQL89 ni tampoco por el SQL92.

SINTAXIS DE INFORMIX

<SENTENCIALOAD> ::= LOAD FROM <nombrefichero> [ DELIMITER <caracter> ] INSERT INTO { tabla | vista | sinónimo } [ ( <listacolumnas> ) ]

Esta sentencia añade nuevas líneas a la tabla. No sobrescribe datos existentes.

El fichero que se especifica en la sentencia LOAD contiene los datos a añadir a la tabla. Si no se incluye la lista de columnas en la cláusula INSERT INTO, los campos en el fichero deben de coincidir con las columnas de la tabla en número, orden y tipo de datos.

Cada línea del fichero debe de tener el mismo número de campos y estos deben de estar separados por el carácter indicado en la cláusula DELIMITER. En caso de omitirse ésta el delimitador por defecto es la barra vertical �|�.

GENERACION DE CODIGO

Esta sentencia no es soportada por ningún otro gestor de bases de datos con una sintaxis similar a la de Informix-SQL, además no todo gestor implementa esta funcionalidad.

Como es importante el proporcionar una forma de hacer carga de datos desde el sistema operativo a una tabla de la base de datos de una forma sencilla e independiente del gestor de bases de datos se define un método en JAVA que implementa la sentencia original de Informix-SQL y que podrá ser utilizado para cualquier gestor de bases de datos. Este método será accesible desde la conexión a la base de datos que haya creada en el programa generado y se llama: load. Recibe 2 ó 3 parámetros que se detallan a continuación:

1. Nombre del fichero del cual se recogen los datos.

2. Delimitador de campos. Es opcional en caso de no ponerse se considerará el delimitador por defecto: � |�

3. Parte insert de la sentencia load.

Page 136: IfxToJava2

136

Para conseguir que el método tenga el comportamiento esperado, en código java, se realizan las siguientes tareas:

Leer del fichero fuente cada línea (fila).

Trocear los campos de cada fila utilizando para ello el delimitador.

Generar una sentencia insert a partir del valor que se recibe como tercer parámetro y los valores troceados leídos del fichero. Ej.

Parámetro: �insert into tabla1�

Línea del fichero: 1|prueba|23.3

Sentencia generada: �insert into tabla1 values (1,�prueba�,23.3)

Para generar la sentencia se ha de tener en cuenta el tipo de dato que recibirá , en base de datos, el valor leído del fichero y en función a él formatear el valor. Éste tipo de dato se obtendrá realizando una consulta a la base de datos.

Ejecutar la sentencia generada sobre el gestor destino.

De esta forma, al utilizar como puente intermedio entre el fichero fuente y el gestor de bases de datos la tecnología JDBC, la sentencia podrá ser ejecutada sobre cualquier gestor de bases de datos.

En el apartado: Ejemplo sentencia load/unload, dentro del Anexo I se plasma un caso del código genrado para esta sentencia.

SENTENCIA LOCK TABLE

Esta sentencia permite controlar el acceso una tabla por parte otros procesos/usuarios.

SINTAXIS DE INFORMIX

<SENTENCIALOCK> ::= LOCK TABLE nombretabla IN { SHARE | EXCLUSIVE } MODE

Un usuario puede bloquear una tabla si es el propietario o tiene privilegios de selección sobre la misma o sobre algún campo. La sentencia LOCK TABLE falla si esta ya esta bloqueada en modo exclusivo por otro proceso.

La palabra SHARE indica que la tabla se bloquea en modo compartido. Esto permite que otros procesos tengan acceso de lectura sobre la tabla pero no de escritura. Otros procesos no pueden alterar o borrar datos si la tabla esta bloqueada en modo compartido.

La palabra EXCLUSIVE bloquea la tabla en modo exclusivo. Este modo no permite a otros procesos ni leer ni escribir sobre la tabla bloqueada. Este bloqueo se produce, también de forma automática, cuando se ejecuta una sentencia: ALTER INDEX, CREATE INDEX, DROP INDEX, RENAME COLUMN, RENAME TABLE, y ALTER TABLE.

Informix-SE no permite que más de un usuario bloquee en tabla en modo SHARED.

SINTAXIS DE SQLSERVER

Hay tres tipos de bloqueos en SqlServer: Shared, Update, y Exclusive. El motor de bases de datos SqlSever gestiona de forma automática los bloqueos necesarios a la hora de lanzar las transacciones sin que el usuario necesite añadir ninguna instrucción especifica para el tratamiento de las mismas, aún así el sistema proporciona la posibilidad de que el usuario trate de influir en las decisiones que el servidor toma utilizando para ello la cláusula WITH en las sentencias: SELECT, UPDATE, DELETE, e INSERT.

SqlServer recomienda que se deje en manos del propio gestor el manejo de los bloqueos ya que los mismos pueden influir mucho en el rendimiento del gestor de bases de datos y la intervención de un usuario inexperto puede afectar negativamente.

Page 137: IfxToJava2

137

La forma en que SqlSever adquiere y libera los bloqueos esta directamente relacionada con el nivel de aislamiento fijado (TRANSACTION ISOLATION LEVEL) y por la granularidad. SqlServer tiene varios niveles de granularidad: una única fila, páginas, extents (grupos de páginas contiguos), o una tabla completa.

A nivel de código se puede influir en el modo en que el servidor se comporta a la hora de realizar los bloqueos utilizando las sugerencias de bloqueos. Sqlserver no admite más de una sugerencia de bloqueo por tabla. Los tipos de sugerencias de bloqueo son:

De granularidad: PAGLOCK, NOLOCK, ROWLOCK, TABLOCK, or TABLOCKX.

De nivel de asilamiento: HOLDLOCK, NOLOCK, READCOMMITTED, REPEATABLEREAD, SERIALIZABLE.

SqlSever tiene limitaciones en el uso de algunas sugerencias de bloqueo, tales como no permite el uso de: NOLOCK, READUNCOMMITTED, o READPAST en las sentencias: DELETE, INSERT o UPDATE, etc.

La definición sintáctica de las sugerencias de bloqueos es:

<sugerencia_de_bloqueos> ::= WITH ( <sugerencia> [, .. n] ) <sugerencia> ::= { INDEX ( index_val [ ,...n ] ) | FASTFIRSTROW | HOLDLOCK | NOLOCK | PAGLOCK | READCOMMITTED | READPAST | READUNCOMMITTED | REPEATABLEREAD | ROWLOCK | SERIALIZABLE | TABLOCK | TABLOCKX | UPDLOCK | XLOCK }

El uso de las sugerencias de bloqueos dentro de las sentencias SQL: SELECT, INSERT, UPDATE, y DELETE se define a continuación de forma resumida:

<sentencia SELECT> ::= SELECT <valores_selecion> FROM tabla <sugerencia_de_bloqueos> �.

<sentencia INSERT> ::= INSERT INTO tabla <sugerencia_de_bloqueos> ��

<sentencia UPDATE> ::= UPDATE tabla <sugerencia_de_bloqueos> SET ��

<sentencia DELETE> ::= DELETE FROM tabla <sugerencia_de_bloqueos> WHERE �.

SINTAXIS DE ORACLE

La sentencia LOCK sobrescribe el bloqueo automático, que gestiona el propio gestor de bases de datos, y permite o deniega el acceso al objeto bloqueado a otros usuarios durante la duración del mismo.

<SENTENCIALOCK> ::= LOCK TABLE [ <esquema> . ] nombretabla IN <lockmode> MODE [ NOWAIT ] <lockmode> ::= ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE | SHARE | SHARE ROW EXCLUSIVE

Page 138: IfxToJava2

138

| EXCLUSIVE SINTAXIS DE DB2 <SENTENCIALOCK> ::= LOCK TABLE nombretabla IN { SHARE | EXCLUSIVE } MODE

GENERACIÓN DE CODIGO

La generación de código para esta sentencia es bastante sencilla. La sentencia original de Informix es soportada por el resto de gestores de bases de datos a excepción de SqlServer el cual gestiona los bloqueos de forma automática.

Otra forma posible es la utilización de transacciones ya que todas las sentencias que forman parte de una transacción se ejecutada como una unidad. Si un controlador de bases de datos soporta transacciones, y casi todos lo hacen, proporcionará algún nivel de protección contra conflictos que puedan surgir cuando los usuarios acceden a los datos a la misma vez. Para evitar conflictos durante una transacción, un controlador de base de datos utiliza bloqueos: mecanismos para bloquear el acceso de otros a los datos que están siendo accedidos por una transacción. La forma en que se configuran los bloqueos está determinada por lo que se llama nivel de aislamiento de transacción.

Teniendo en cuenta, como se verá en la sentencia UNLOCK, que: para el resto de gestores el bloqueo de una tabla finaliza cuando se termina la transacción en la cual la misma esta implicada y que las transacciones aportan por sí mismas un nivel de bloqueo las sentencias que estén, en código fuente, entre la sentencia LOCK y UNLOCK formarán parte de una transacción siempre y cuando el gestor de bases de datos lo permita. Ejemplo:

Código fuente:

LOCK TABLE tabla1 IN SHARE MODE

INSERT INTO tabla1 VALUES (1, 2,�tres�)

UPDATE tabla1 SET campo1 = 3 WHERE campo1 = 2

UNLOCK TABLE

Código objeto para el reto de gestores:

Connection.setAutoCommit(false); Desactiva el modo autoentrega

[ Sent.exeUpdate (�LOCK TABLE tabla1 IN SHARE MODE�); ]

sent. exeUpdate(�INSERT INTO tabla1 VALUES (1,2,�tres�)� );

sent. exeUpdate(�UPDATE tabla1 SET campo1 = 3 WHERE campo1 = 2 �);

Connection.commit();

[ Sent.exeUpdate (�UNLOCK TABLE tabla1�); ]

Connection.setAutoCommit(true); Finaliza la transacción.

La sentencia LOCK se generará para todos los gestores menos SqlServer y la sentencia UNLOCK únicamente para Informix-SQL. En todo caso las sentencias a ejecutar se incluyen dentro de una transacción. En el Anexo I, apartado: Ejemplo sentencia lock/unlock se pueden ver ejemplos prácticos.

SENTENCIA OPEN

La sentencia OPEN permite activar un cursor, asociado con una sentencia DECALRE o EXECUTE, y por tanto la ejecución del mismo.

Page 139: IfxToJava2

139

SINTAXIS DE INFORMIX

<SENTENCIAOPEN> ::= OPEN nombrecursor [ USING { <variable> [,...n] } ]

La parte USING de la sentencia OPEN puede ser requerida cuando el cursor esta asociado con una sentencia preparada. Cada variable se sustituirá por cada aparición del símbolo de interrogación (?) de la sentencia preparada.

SINTAXIS DE SQLSERVER

<SENTENCIAOPEN> ::= OPEN { { [GLOBAL] nombrecursor } | nombrevariablecursor}

SINTAXIS DE ORACLE

<SENTENCIAOPEN> ::= OPEN nombrecursor [ ( <variable> [,...n] ) ]

SINTAXIS DE DB2

<SENTENCIAOPEN> ::= OPEN nombrecursor [ USING { <variable> [,...n] } | [ USING DESCRIPTOR nombredescriptor ]

GENERACIÓN DE CODIGO

La generación de código de esta sentencia se verá en el apartado: Sentencias de manipulación dinámica de datos y cursores.

SENTENCIA PREPAPRE

Esta sentencia permite analizar, validar, y generar un plan de ejecución de una sentencia SQL.

SINTAXIS DE INFORMIX

<SENTENCIAPREPARE> ::= PREPARE nombresentpreparada FROM {<variable> | cadena }

SINTAXIS DE SQLSERVER

<SENTENCIAPREPARE> ::= PREPARE nombresentpreparada [INTO sqlca] FROM { <variable> | cadena } [, ..n]

Prepara la sentencia SQL deSde la cadena de caracteres que recibe como parámetro para posteriormente ser ejecutada.

nombresentpreparada puede posteriormente formar parte de una sentencia EXECUTE, o DECLARE CURSOR.

SINTAXIS DE ORACLE

<SENTENCIAPREPARE> ::= PREPARE nombresentpreparada FROM { cadena | variable }

SINTAXIS DE DB2

<SENTENCIAPREPARE> ::= PREPARE nombresentpreparada [ [OUTPUT] INTO nombre_descriptor ] [ INPUT INTO nombre_descriptor ] FROM <variable>

GENERACIÓN DE CODIGO

Esta sentencia se usa bien asociada a la sentencia EXECUTE o bien asociada a la sentencia DECLARE dentro del manejo de cursores.

Page 140: IfxToJava2

140

A la hora de traducirla a código objeto se utilizará la sentencias propias del JDBC de JAVA consiguiendo así un tratamiento estándar para todos los gestores de bases de datos estudiados y no ciñéndose a la sintaxis que proporcione cada uno de ellos para el tratamiento de las sentencias preparadas y los cursores.

La sentencia SQL que se procesa mediante la sentencia PREPARE no será evaluada. Esta vendrá en una constante o una variable tipo cadena caracteres y no se tendrá en cuenta si es valida o no para el gestor de bases de datos destino. Esto se indicará durante la generación de código a través de un warning:

Warning: Sentencia PREPARE, revisar sintaxis SQL

En la sección de generación de código dentro de la: Sentencia EXECUTE se ve un caso práctico de utilización del binomio de sentencias PREPARE-EXECUTE.

En la sección: Sentencias de manipulación dinámica de datos y cursores se mostrarán ejemplos de esta sentencia junto con la sentencia DECLARE así como las peculiaridades de su traducción y tratamiento.

SENTENCIA PUT

Esta sentencia guarda una fila en la base de datos cuyos datos fueron almacenados en memoria por la sentencia FLUSH.

<PUT>::= PUT nombre_cursor [ FROM <variable> [, .. n] ]

SENTENCIA RENAME COLUMN

Esta sentencia permite cambiar el nombre de una columna de una tabla.

Esta sentencia no esta contemplada por SQL92, es una extensión que aporta Informix-SQL, y no es soportada en el mismo aspecto que Informix-SQL por ningún otro gestor de bases de datos de los contemplados aquí.

SINTAXIS DE INFORMIX

<SENTENCIARENAMECOLUMN> ::= RENAME COLUMN nombretabla . nombredecolumna TO nuevonombredecolumna

SINTAXIS DE SQLSERVER

<SENTENCIARENAMECOLUMN> ::= sp_rename �nombretabla. Nombredecampo�, � nombrenuevocampo� , 'COLUMN'

En SQLSERVER no se contempla ninguna sentencia que permita renombrar un campo de una tabla, pero si existe un procedimiento almacenado que posibilita hacerlo.

SINTAXIS DE ORACLE

Oracle no define la sentencia RENAME pero, a partir de la versión 9i reléase 2, sí permite modificar el nombre de una columna utilizando para ello la sentencia ALTER TABLE, la sintaxis es:

<SENTENCIARENAMECOLUMN> ::= ALTER TABLE nombretabla RENAME COLUMN nombre columna TO nuevonombrecoluma

SINTAXIS DE DB2

El gestor de base de datos DB2 no soporta esta funcionalidad.

GENERACIÓN DE CODIGO

Aunque la sintaxis original de Informix-SQL no es soportada por ningún otro gestor si se generará esta sentencia, para aquellos que la soportan, utilizando la sintaxis apropiada para el gestor de base de datos destino. Para el caso de DB2 no se generará y se indicará a través de un warning durante el proceso de traducción:

Page 141: IfxToJava2

141

Warning: Sentencia RENAME no generada

Para ver casos prácticos del comportamiento del traductor respecto a esta sentencia dirigirse a: Ejemplo sentencia rename column, dentro del Anexo I.

SENTENCIA RENAME TABLE

Esta sentencia permite cambiar el nombre de una de una tabla de la base de datos actual.

Esta sentencia no esta contemplada por SQL92, es una extensión que aporta Informix-SQL, aunque de una forma u otro todos los gestores aquí estudiados la contemplan.

SINTAXIS DE INFORMIX

<SENTENCIARENAMETABLE> ::= RENAME TABLE nombretabla TO nuevonombredetabla

SINTAXIS DE SQLSERVER

<SENTENCIARENAMETABLE> ::= sp_rename nombretabla, nombrenuevotabla

En SQLSERVER no se contempla ninguna sentencia que permita renombrar una tabla, pero si existe un procedimiento almacenado que posibilita hacerlo.

SINTAXIS DE ORACLE

<SENTENCIARENAMETABLE> ::= ALTER TABLE nombretabla RENAME TO nuevonombredetabla

SINTAXIS DE DB2

<SENTENCIARENAMETABLE> ::= RENAME TABLE nombretabla TO nuevonombredetabla

GENERACIÓN DE CODIGO

La generación de código de esta sentencia no plantea ningún problema solo se a de atender a la sintaxis particular de cada gestor de bases de datos. En el Anexo I, hay un caso práctico de código generado para esta sentencia, dentro del apartado: Ejemplo sentencia rename tabla.

SENTENCIA REVOKE

Quita un permiso otorgado o denegado previamente de un usuario de la base de datos actual.

Esta sentencia es contemplada por el estándar SQL92 pero de forma más limitada a como lo hace el gestor de bases de datos Informix-SQL. Este contempla permisos a nivel de objetos y de bases de datos , el estándar solo a nivel de objetos.

SINTAXIS DE INFORMIX

<SENTENCIAREVOKE> ::= REVOKE [ <privilegiosniveldetabla> ON <tabla> | <privilegiosniveldebasedatos> ] FROM [ PUBLIC | <usuarios> ] <tabla> ::= nombretabla | nombrevista | nombresinonimo

<usuarios> ::= usuario [ �n]

<privilegiosniveldetabla> ::= ALL [ PRIVILEGES ] | { INSERT | DELETE | SELECT | UPDATE | INDEX | ALTER } [...n]

Page 142: IfxToJava2

142

<privilegiosniveldebasedatos> ::= CONNECT | RESOURCE | DBA

SINTAXIS DE SQLSERVER

<SENTENCIAREVOKE> ::= REVOKE [ GRANT OPTION FOR ] { ALL [ PRIVILEGES ] | <permisos> [ ,...n ] } { [ ( columna [ ,...n ] ) ] ON { tabla | vista } | ON { tabla | vista } [ ( columna [ ,...n ] ) ] | ON { procedimientoalmacenado | procedimientoexetendido } | ON { funcionesdefinidasporelusuario } } {TO | FROM} cuentadeseguridad [ ,...n ] [ CASCADE ] [ AS { grupo | rol } ]

<permisos> ::= SELECT | INSERT | DELETE | UPDATE | REFERENCES | EXECUTE

cuentadeseguridad hace referencia a una cuenta de usuario de la base de datos.

SINTAXIS DE ORACLE

< SENTENCIAREVOKE> ::= REVOKE <privilegios> ON <tabla> FROM <usuarios> <privilegios> ::= ALL | SELECT | INSERT | DELETE | UPDATE ( columna [�n] )

<usuarios> ::= usuario [ �n]

<tabla> :.= nombretabla | nombrevista | nombresinonimo

SINTAXIS DE DB2

< SENTENCIAREVOKE> ::= REVOKE <privilegios> ON [TABLE] [tabla | vista] FROM <usuarios> <privilegios> ::= ALL [PRIVILEGES] | SELECT | INSERT | DELETE | UPDATE | INDEX | REFERENCES | CONTROL | ALTER <usuarios> ::= { PUBLIC | [USER | GROUP ] cuentadeseguridad } [,�n]

Page 143: IfxToJava2

143

GENERACIÓN DE CODIGO

Al igual que ocurría con la sentencia GRANT la solución planteada será la misma. Si se trata de quitar permisos a nivel de base de datos, al considerarse esto como una tarea de administración, no se generará código, pero si se trata de permisos a nivel de objeto sí. A la hora de procesar el código fuente se indicará por pantalla, si se trata de permisos a nivel de bases de datos, el siguiente mensaje:

Línea: 4 Warning: Sentencia REVOKE no generada

SENTENCIA ROLLBACK WORK

Esta sentencia marca el fin de una transacción no correcta y hace que todas las modificaciones efectuadas sobre los datos desde el inicio de la transacción sean deshechas.

Esta sentencia no es incorporada ni por el estándar SQL89 ni por el estándar básico SQL92 aunque todos los gestores de bases de datos la incorporan, incluido Informix-SQL, razón por la cual se incorpora a la hora de traducir el código fuente.

Al igual que ocurría con la sentencia BEGIN WORK cada gestor incorpora su propia sentencia pero la solución que se adoptará a la hora de generar código es independiente del gestor y se basa en las posibilidades que aporta el JDBC de JAVA. Por esta razón no nos pararemos a estudiar en detalle la sentencia del resto de gestores.

SINTAXIS DE INFORMIX

<ROLLBACK WORK> ::= COMMIT WORK

GENERACIÓN DE CODIGO

La generación de código, al igual que con la sentencia BEGIN WORK, se hace de forma independiente al gestor de base de datos para el cual se este traduciendo. La traducción será la siguiente:

Connection.rollback();

Connection.setAutoCommit (true);

Este código hace dos acciones, primero hace que la modificaciones efectuadas desde el inicio de la transacción no pasen a forma parte de la base de datos de forma permanente; y segundo cierra la transacción.

El código objeto obtenido de las sentencias de tratamiento de transacciones no será dependiente del gestor de bases de datos ya que se utilizan funcionalidades propias del API JDBC. En el punto: Ejemplo sentencias de tratamiento de transacciones, perteneciente al Anexo I se muestran ejemplos prácticos.

SENTENCIA SELECT

Esta sentencia permite hacer una consulta sobre la base de datos.

SINTAXIS DE INFORMIX

<SENTENCIA SELECT> ::= SELECT [ ALL | DISTINCT | UNIQUE ] <listaselect> [ INTO <listadecampos> ] FROM <tablafuente> [ WHERE <condiciondebusqueda> ] [ GROUP BY <expresiongroupby> ] [ HAVING <condiciondebusqueda> ] [ ORDER BY <expresiondeordenacion> [ ASC | DESC ] ] [ INTO TEMP nombretablatemporal [ WITH NO LOG ] ] <listaselect> ::= { *

Page 144: IfxToJava2

144

| { nombretabla | nombrevista | aliasdetabla }.* | { nombrecolumna | expresión | }[ [ AS ] aliasdecolumna ] } [,...n ] <listadecampos> ::= <variable> [,�n] <tablafuente>::= <tabla> [ [AS] aliasdetabla ] , <uniondetablas> [,�n]

<uniontablas> ::= <tabla> [ [AS] aliasdetabla ] | OUTER <tabla> [ [AS] aliasdetabla ] | OUTER ( <tabla> [ [AS] aliasdetabla ] , <uniondetablas> )

<tabla> ::= { tabla | vista | sinónimo }

<condiciondebusqueada ::= <condición>

<expresiongroupby> ::= { [ {nombretabla | nombrevista | sinónimo | aliasdetabla } . ] nombrecolumna | númeroselect } [,...n ] <expresiondeordenacion> ::= { [ {nombretabla | nombrevista | sinónimo | aliasdetabla } . ] nombrecolumna | númeroselect | aliasdecampo | rowid } [,...n ]

SINTAXIS DE SQLSERVER

<SENTENCIA SELECT> ::= SELECT <clausulasselect> <listaselect> [ INTO tablanueva ] FROM <tablafuente> [ WHERE <condiciondebusqueda> ] [ GROUP BY <expressiongroupby ] [ HAVING <condiciondebusqueda ] [ ORDER BY <expression> [ ASC | DESC ] ] <clausulasselect> ::= [ ALL | DISTINCT ] [ TOP n [PERCENT] [ WITH TIES] ] <listaselect> ::= { * | { nombretabla | nombrevista | aliasdetabla } . * | { nombrecolumna | expresion | IDENTITYCOL | ROWGUIDCOL } [ [ AS ] aliasdecolumna ] | column_alias = expression } [ ,...n ] <tablafuente> ::= { nombretabla [ [ AS ] aliasdetabla ] [ WITH ( < tabla_hint > [ ,...n ] ) ] | nombrevista [ [ AS ] aliasdetabla ] [ WITH ( < vista_hint > [ ,...n ] ) ] | función [ [ AS ] aliasdetabla ] | funciondefinidaporelusuario [ [ AS ] aliasdetabla ] | tabladerivada [ AS ] aliasdetabla [ ( aliasdecolumna [ ,...n ] ) ] | < uniondetablas > } [ ,...n ]

Page 145: IfxToJava2

145

<uniondetablas> ::= <tablafuente> <tipodeunion> <tablafuente> ON <condiciondebusqueda> | <tablafuete> CROSS JOIN <tablafuente > | [ ( ] < uniondetablas > [ ) ] <tipodeunion> ::= [ INNER | { { LEFT | RIGHT | FULL } [ OUTER ] } ] [ <tipodeunion> ] JOIN <expresiongroupby> ::= [ ALL ] <expression> [ ,...n ] [ WITH { CUBE | ROLLUP } ]

SINTAXIS DE ORACLE

<SENTENCIA SELECT> ::= SELECT <clausulasselect> <listaselect> FROM <tablafuente> [ WHERE <condiciondebusqueda> ] [ GROUP BY <expressiongroupby ] [ HAVING <condiciondebusqueda ] [ ORDER BY <expresiondeordenacion> <clausulasselect> ::= [ ALL | DISTINCT ] <listaselect> ::= { * | [esquema . ]{ nombretabla | nombrevista | aliasdetabla } . * | { nombrecolumna | expresión }[ [ AS ] aliasdecolumna ] } [ ,...n ] <tablafuente> ::= [esquema . ] { nombretabla [ [ AS ] aliasdetabla ] | nombrevista [ [ AS ] aliasdetabla ] | ( <expresión> ) [ [ AS ] aliasdetabla ] | < uniondetablas > } [,...n ] <uniondetablas> ::= <tablafuente> <tipodeunion> <tablafuente> ON <condiciondebusqueda> | <tablafuete> CROSS JOIN <tablafuente > | [ ( ] < uniondetablas > [ ) ] <tipodeunion> ::= [ INNER | { { LEFT | RIGHT | FULL } [ OUTER ] } ] [ <tipodeunion> ] JOIN <expresiongroupby> ::= <expresión> [ ,...n ] <expresiondeordenacion> ::= { <expresión> | <posicion> | tabla | aliasdetabla } [ ASC | DESC ] ] [,�n]

Page 146: IfxToJava2

146

SINTAXIS DE DB2

<SENTENCIA SELECT> ::= <clausulaselect> <clausulafrom> [ <clausulawhere> ] [ <clausulagroupby> ] [ <clausulahaving> ] [ <clausulaorderby ] [ <clausulafetch_first> ] <clausulaselect> ::= SELECT [ ALL | DISTINCT ] { * | <expresión> . * | <expresión> [ AS ] aliasdecolumna ] } [,...n] c <clausulaform> ::= FROM <definiciontabla> [, ..n] <definiciontabla> ::= { <nombretabla> | [ ONLY | OUTER] { nombretabla | nombrevista } } <clausulacorrelacion> | <uniondetablas> <nombretabla> ::= { nombretabla | nombrevista | nickname } <clausulacorrelacion> ::= AS nombre [ ( nombre_columna [, ..n] ) ] <uniondetablas> ::= <tabla> [ [AS] aliasdetabla ] | OUTER <tabla> [ [AS] aliasdetabla ] | OUTER ( <tabla> [ [AS] aliasdetabla ] , <uniondetablas> ) <clausulawhere> ::= WHERE <condiciondebusqueda> <clausulagroupby> ::= GROUP BY <expression> [, ..n] <clausulahaving> ::= HAVING <condiciondebusqueda> <clausulaorderby> ::= ORDER BY <elementoordenacion> [ ASC | DESC ] [, ..n]

GENERACIÓN DE CODIGO

Las sentencias del resto de gestores de bases de datos son mayormente compatibles con la que define Informix-SQL. Cabe destacar que ningún otro gestor soporta la opción: INTO <variable> para almacenar el resultado de la consulta a la tabla y que Oracle y Db2 tampoco soportan el insertar los datos obtenidos en otra tabla, temporal o no, de la base de datos.

Aparte de estos problemas esta sentencia plantea otros muchos temas a tener en consideración:

Utilización de variables definidas por programa.

Utilización de expresiones agregadas y funciones SQL.

Tipos de datos.

Utilización de expresiones y operaciones con las mismas.

Etc.

Page 147: IfxToJava2

147

Todas estos temas se tratarán en secciones posteriores con total detalles y atendiendo a las peculiaridades de cada gestor de bases de datos.

La forma en que se generará código objeto solucionará el problema de la cláusula INTO <variable> ya que se utilizarán los métodos propios del API JDBC de JAVA para lanzar las sentencias contra el gestor y para la recuperación de los datos. En cuanto a la cláusula INTO TEMP <tabla> no será analizada en esta versión.

Dentro de los ejemplos mostrados en el Anexo I, se pueden ver varios casos del uso esta sentencia.

SENTENCIA START

Esta sentencia permite establecer la conexión con la base de datos. Es una ampliación a la versión 4.10 de Informix-SQL (al igual que CONNECT), y semánticamente es equivalente a la sentencia DATABASE por esta razón será contemplada en el traductor.

SINTAXIS DE INFOMRIX

<SENTENCIA START> ::= START DATABASE <nombrebasedatos>

GENERACIÓN DE CÓDIGO

La traducción de esta sentencia a código objeto será, al igual que con la sentencia DATABASE, de forma independiente al gestor de bases de datos destino y aprovechando las funcionalidades que aporta el API JDBC de JAVA, ver ejemplo en: Ejemplo sentencias conexión/desconexión.

SENTENCIA UNLOAD

Esta sentencia permite descargar datos de en una tabla, vista o sinónimo de la base de datos a un fichero del sistema operativo.

Al igual que ocurría con la sentencia LOAD esta sentencia no es soportada por el estándar SQL89 ni tampoco por el SQL92 la incorpora Informix-SQL como una funcionalidad adicional.

SINTAXIS DE INFORMIX

<SENTENCIA UNLOAD> ::= UNLOAD FROM <nombrefichero> [ DELIMITER <caracter> ] <sentencia select>

Esta sentencia descarga filas de la tabla. No elimina las filas descargadas de la tabla origen.

El fichero que se especifica en la sentencia UNLOAD contendrá los datos a descargar de la tabla.

En caso de omitirse el delimitador por defecto es la barra vertical �|�.

GENERACION DE CODIGO

Esta sentencia no es soportada por ningún otro gestor de bases de datos con una sintaxis similar a la de Informix-SQL y no todo gestor implementa esta funcionalidad.

Al igual que se hizo en la sentencia LOAD y aún conociendo que existen sentencias similares en algún otro gestor y por las mismas circunstancias se implementa la sentencia UNLAOD en JAVA.

El método definido se llamará unload y se definirá en una clase accesible en tiempo de ejecución. Recibe 2 ó 3 parámetros:

1. Nombre del fichero en el cual se descargan los datos.

2. Delimitador de campos. Es opcional en caso de no ponerse se considerará el delimitador por defecto: �|�

3. Subsentencia select.

Page 148: IfxToJava2

148

Para conseguir que el método tenga el comportamiento esperado, en código java, se realizan las siguientes tareas:

Coger la parte select de la sentencia original y lanzarla contra la base de datos.

Leer cada fila de la consulta campo a campo.

Construir una cadena con la correlación de campos, correspondientes a la consulta realizada a la base de datos, separados por el campo delimitador y mandarlo al fichero resultado indicado en la sentencia.

De esta forma, al utilizar como puente intermedio entre el fichero fuente y el gestor de bases de datos la tecnología JDBC, la sentencia podrá ser ejecutada sobre cualquier gestor de bases de datos.

En el ejemplo mostrado al analizar la sentencia: SENTENCIA LOAD FROM , también se muestra la utilización de la sentencia UNLOAD.

UNLOCK TABLE

SINTAXIS DE INFORMIX

<SENTENCIAUNLOCK> ::= UNLOCK TABLE { nombretabla | nombresinonimo }

Un usuario puede desbloquear una tabla si es el propietario o tiene privilegios de selección sobre la misma o sobre algún campo. No se podrán desbloquear tablas que no hayan sido bloqueadas por el mismo usuario. Solo se puede aplicar un bloqueo sobre una tabla al mismo tiempo.

SINTAXIS DE SQLSERVER

Como se comento al tratar la sentencia LOCK SqlServer no se encarga del manejo de bloqueos de forma automática.

SINTAXIS DE ORACLE

Oracle no contempla la sentencia UNLOCK el bloqueo se mantiene hasta el fin de la transacción activa.

SINTAXIS DE DB2

En Db2 tampoco se contempla la sentencia UNOLOCK el sistema mantiene el bloqueo sobre la tabla hasta el fin de la transacción activa.

GENERACIÓN DE CODIGO

Al explicar la sentencia: SENTENCIA LOCK TABLE se comento también la forma de tratar esta sentencia.

SENTENCIA UPDATE

La instrucción UPDATE puede cambiar los valores de filas individuales, grupos de filas o todas las filas de una tabla. Una instrucción UPDATE que haga referencia a una tabla sólo puede cambiar los datos de una tabla a la vez.

Esta sentencia es soportada por el estándar SQL92. La sentencia proporcionada por Informix-SQL se adapta en su totalidad al estándar SQL92 lo que facilitará mucho su traducción al resto de gestores de base de datos.

SINTAXIS DE INFORMIX

<SENTENCIAUPDATE> ::= UPDATE { nombretabla | nombresinonimo | nombrevista } SET <clausulaset> [ <clausulawhere> ]

Page 149: IfxToJava2

149

<clausulaset> ::= { nombrecolumna = { <expresión> | <sentenciaselect> | <variable> } } [, �n] | ( { nombrecolumna | * | <tabla> .* }[,�n] ) = ( { <expresión> | ( <sentenciaselect> ) | <variablecompleja> } [,�n] ) <variablecompleja> ::= <variable> . * | <variable> . valor <clausulawhere> ::= WHERE { <condición> | CURRENT OF nombrecursor }

SINTAXIS DE SQLSERVER

<SENTENCIAUPDATE> ::= UPDATE { nombretabla WITH ( < sujerencias_de_alteracion > [ ..n ] ) | nombrevista | nombresinonimo } SET { nombrecolumna = { <expresión> | DEFAULT | NULL} | @variable = expresión | @variable = column = <expresión> } [ , ..n ] } [, ..n] { { [ FROM { <nombretabla> } [ , ...n ] ] [ WHERE <condicion_de_busqueda> ] } | [ WHERE CURRENT OF [ GLOBAL ] nombrecursor ] } [ OPTION ( < sugerencias_de_busqueda > [ ,...n ] ) ]

SINTAXIS DE ORACLE

<SENTENCIAUPDATE> ::= UPDATE <sugerencia_de_update> { esquema . { nombretabla | nombrevista | nombresinonimo } [ @basedatos] | ( <subconsulta> [ <condiciones_subconsulta> ] ) } [ sinonimoobjeto ] SET { nombrecolumna = { <expresión> | DEFAULT | <subconsulta>} | ( nombrecolumna [, ..n] ) = ( <subconsulta> ) } [, ..n] [ WHERE <condicion_de_busqueda> | WHERE CURRENT OF nombrecursor ] [ RETURNING <expresión> [, ..n] INTO <variable> [, ..n] ]

SINTAXIS DE DB2

<SENTENCIAUPDATE> ::= UPDATE { { nombretabla | nombrevista | nombresinonimo } | ONLY [ nombretabla | nombrevista ] } [ AS sinonimoobjeto ] SET { nombrecolumna = { <expresión> | DEFAULT | <NULL>} | ( nombrecolumna [, ..n] ) = ( [<expresión> | DEFAULT | <NULL> ] | <subconsulta> ) } [, ..n] [ WHERE <condicion_de_busqueda> | WHERE CURRENT OF nombrecursor ] [ WITH { RR | RS | CS | UR } ]

Page 150: IfxToJava2

150

GENERACIÓN DE CODIGO

Observando la sentencia original de Informix-SQL y la que proporciona el resto de gestores se ve que es totalmente compatible.

A lo largo de los ejemplos mostrados en el Anexo I se puede ver ejemplos de generación de código para esta sentencia. Dentro de la sección: Sentencias de manipulación dinámica de datos y cursores se muestran ejemplos de esta sentencia con la opción: WHERE CURRENT OF.

UPDATE STATISTICS

Esta sentencia permite actualizar el catalogo de tablas del sistema que el servidor utiliza para optimizar las búsquedas.

SINTAXIS DE INFORMIX

<SENTENCIAUPDATESTATISTICS> ::= UPDATE STATISTICS

GENERACIÓN DE CODIGO

Esta es una sentencia y pura de administración que se suele ejecutar con el objeto de optimizar el rendimiento de la base de datos. Cada gestor proporciona sus propios métodos o forma de realizarla a través de la herramienta de administración. No se generará código objeto para la misma.

SENTENCIAS DE MANIPULACIÓN DINÁMICA DE DATOS Y CURSORES En este apartado se quiere hacer un tratamiento especial de los cursores atendiendo a la forma en que se ha decido se genere código objeto. Las instrucciones SQL que trabajan con cursores son: CLOSE, DECLARE CURSOR FOR, DELETE FROM � WHERE CURRENTO OF, EXECUTE, FETCH, FLUSH, FREE, OPEN, PREPARE, PUT, y UPDATE � WHERE CURRENT OF.

La sintaxis de todas estas sentencias ya se describió en las secciones anteriores en las cuales se analizaba cada uno de ellas. Como se comento no todas las sentencias son soportadas en igual medida por el resto de gestores de bases de datos pero en este caso no genera ningún problema ya que se van a aprovechar las posibilidades que proporciona el API JDBC de JAVA para el manejo de cursores.

La forma típica de definición de un cursor en Informix-SQL es:

DECLARE c5 cursor FO �select * from tabla1�

OPEN c1

FETCH c5 INTO x, y

CLOSE c5

Donde la sentencia a ejecutar se puede colocar directamente detrás del DECALRE o bien venir definida a través de una sentencia PREPARE.

Este grupo de sentencias se trasformará, para todo gestor, de la siguiente forma:

Statement ASG_sp_c5 =

ASGdb.retCon().createStatement(ResltSet.TYPE_XXXXX, ,ResultSet.CONCUR_XXXXXXX);

ResultSet ASG_rsp_c5 = ASG_sp_c5.executeQuery("select max ( * ) from tabla1");

Try {

ASG_rsp_c5.next();

Page 151: IfxToJava2

151

vuno = ASG_rsp_c5.getShort(1);

} catch (SQLException e) {}

ASG_rsp_c5.close();

ASG_sp_c5.close();

Observando la sentencia generada se pueden ver varias cosas:

No existe una correlación exacta entre sentencia origen y objeto, la correlación real es:

DECLARE con: createStatement o prepareStatement y executeQuery

OPEN no genera código objeto

FETCH con: next y getXXX

CLOSE con el close del RestultSet y del Statement.

Se utilizan variables de programa JAVA no definidas en el código fuente y dejan de utilizarse nombre de cursores si definidos en el código fuente. Informix-SQL no permite que dos cursores, dentro de un mismo programa, se nombren igual, pero si permite que un cursor se nombre igual que una variable.

Aquí se ha de tener especial cuidado al definir las variables que se asocian a los cursores para evitar que se generen errores debido a nombres de variables duplicados. Para ello las variables necesarias para la transformación de los cursores a código objeto se nombrarán siguiendo la siguiente estructura:

Un sufijo generado en función de la sentencia:

Para Statement será: ASG_sp (de sentencia preparada)

Para el ResultSet será ASG_rsp (de resulset de la sentencia preparada)

Y una parte final que corresponderá con el nombre del cursor definido en el código fuente.

La sentencia que permite definir las opciones del cursor es: createStatement a través de sus parámetros, que son:

Primer parámetro marca el modo de funcionamiento del cursor y la posibilidad de actualización de la vista de los datos si estos han sido modificados por otro usuario. Los valores que puede tomar son:

ResultSet.TYPE_FORWARD_ONLY. Solo se puede recorrer el cursor hacia delante. Valor por defecto.

ResulSet.TYPE_SCROLL_INSENSITIVE. Permite recorrer el cursor en ambos sentidos y no se ve afectados por cambios realizados en base de datos por otros usuarios.

ResultSet.TYPE_SCROLL_SENSITIVE: permite recorrer el resultado usando un cursor bidireccional y además permite actualizar el cursor con los cambios que se hayan producido en la base de datos.

El segundo parámetro marca la posibilidad de alterar el valor de los campos de la fila a la que apunta el cursor y puede tomar los valores:

ResultSet.CONCUR_READ_ONLY. Los valores son solo lectura, no se pueden modificar. Valor por defecto.

ResultSet.CONCUR_UPDATABLE. Indica que el valor de cursor puede ser actualizado en la base de datos. Esta opción posibilita que la opción FOR UPDATE del código fuente pueda ser aplicable a través de JAVA.

Según la definición sintáctica, por defecto estos parámetros deben de ser: TYPE_SCROLL_SENSITIVE y CONCUR_READ_ONLY. En el caso de que se utilice la opción SCROLL el primer parámetro será: TYPE_SCROLL_INSENSITIVE y si se utiliza la opción FOR UPDATE el

Page 152: IfxToJava2

152

segundo parámetro será: CONCUR_UPDATABLE. Por definición sintáctica no se puede ver que nunca coincidirán las opciones FOR UPDATE y SCROLL. Destacar aquí que Db2 no admite la combinación: SCROLL_SENSITIVE y CONCUR_UPDATABLE en este caso se utilizará SCROLL_INSENSITIVE Y CONCUR_UPDATABLE.

En el punto: Ejemplo sentencia prepare/execute � prepare/declare del Anexo I se puede ver ejemplo del tratamiento de esta sentencia. En este ejemplo se muestra, también, un caso completo de utilización de un cursor con la sentencias DECLARE-OPEN-FETCH-CLOSE con y sin la sentencia PREPARE.

FOR UPDATE

Cuando se pone la opción FOR UPDATE tras la subsentencia SELECT de la sentencia DECLARE CURSOR significa que a la hora de tratar las filas se genera un bloqueo especial por la posibilidad de que se actualicen campos de la fila que se esta procesando o se borre está, usando para ello la opción WHERE CURRENT OF de las sentencias UPDATE o DELETE.

La forma de indicar la opción FOR UPDATE al declarar el cursor, en el momento de generar código, es utilizando el parámetro: ResultSet.CONCUR_UPDATABLE del método createStatement o prepareStatement.

Aunque aparentemente no se manejan cursores en el código JAVA generado, internamente el JDBC los utiliza. Existen varios métodos para el tratamiento de la opción WHERE CURRENT OF, como son:

El método: getCursorName(), proporcionado por el API JDBC 2.0, que nos permite recuperar el cursor actual. La utilización de este método es la forma más transparente y sencilla a la hora de traducir código fuente a objeto, como se muestra a continuación:

Código fuente: update tabla1 set campo1 = 4 where current of c4

Código objeto: Statement.executeUpdate("update tabla1 set campo1 = 4 where current of "+ ResultSet.getCursorName());

El problema que tiene este método propuesto es que no es implementado por tordos los drivers JDBC, por ejemplo SqlServer y Oracle no lo soportan. Para estos casos existen otras posibilidades de tratar esta cláusula que se muestras seguidamente.

métodos: updateRow y deleteRow. Estos métodos, del API JDBC 2.0, proporcionan realizar operaciones de actualización/eliminación que afectan a la fila en la que se encuentra el cursor. Ejemplo:

Código objeto: ResultSet.next(); posicionamiento del cursor.

ResultSet.updateShort(�campo1�, 4);

ResultSet.updateRow();

Esta forma de realizar la traducción de la opción WHERE CURRENT OF aunque también es parte de las funcionalidades estándar proporcionadas por el API JDBC tampoco funciona para todos los gestores de bases de datos. En el caso de Oracle falla en ciertos casos como cuando la subsentencia SELECT del DECLARE CURSOR es del tipo: �select * �� en lugar de: �select camposx, campoy ��.

Este sistema implica:

Un cambio radical entre el código fuente y el código objeto.

Ser capaces de determinar el tipo de dato que se va a alterar en la tabla de la base de datos para utilizar el método correcto updateXXXX.

Rowid. La utilización de este método solo puede aplicarse para gestores de bases de datos en particular y utilizando métodos específicos del API JDBC proporcionado por el proveedor. Este método se basa en para cada fila que se procese obtener también el ROWID y a la hora de ejecutar la sentencia UPDATE o DELETE utilizarlo en la cláusula WHERE. Ejemplo:

Código objeto: �. select campo1, campos, rowid where �

Page 153: IfxToJava2

153

Object ob1 = getObject(1);

�����

String variablerowid = getString(posición);

Statement.executeUpdate("update tabla1 set campo1 = 4 where ROWID = � + variablerowid);

Este sistema implica:

Modificar la subsentencia SELECT del DECLARE CURSOR de tal forma que el obtenga el valor del rowid. Ejemplo:

Código fuente: declare c1 cursor for select * from tabla1

Código fuente a traducir: declare c1 cursor for select *, rowid from tabla1

Recuperar en una variable tipo String el valor del campo rowid para luego utilizarlo en la sentencia UPDATE o DELETE.

En el Anexo I, apartado: Ejemplo sentencia declareforupdate muestran varios ejemplos así como su tratamiento por parte del traductor para obtener código objeto valido.

SENTENCIAS DE CONTROL DE FLUJO En este apartado se estudia la sentencia FOREACH que aunque no es una sentencia SQL es la única sentencia de control de flujo que se usa exclusivamente para recorrer cursores loa cuales si están directamente ligados a sentencias SQL.

Sintaxis:

<SENTENCIA FOREACH> ::= FOREACH cursor [INTO variable_de_programa] <sentencias> END FOREACH

El funcionamiento de esta sentencia no es más que el del recorrido secuencial de todos los elementos del cursor. Su traducción a código objeto JAVA se realizará como el resto de sentencias de manejo de cursores, de forma independiente al gestor y siguiendo las reglas indicadas en el punto anterior, de la siguiente forma:

Código fuente:

foreach c1 into vuno, vdos, vtres Message �campos: �,vuno, vdos, vtres end foreach

Código objeto:

while ( ASG_rsp_c1.next() ) { vuno = ASG_rsp_c1.getShort(1); vdos = ASG_rsp_c1.getDouble(3);

vtres = ASG_rsp_c1.getString(2); System.out.println(�campos:� + vuno + vtres + vdos ); }

En la sección Anexo I dentro del punto: Ejemplo sentencia foreach-forupdate se muestran varios ejemplos de traducción y utilización de esta sentencia tanto de forma simple como con la opción FOR UPDATE.

Page 154: IfxToJava2

154

ESTUDIO DE TIPOS DE DATOS En una tabla de la base de datos se pueden almacenar diferentes tipos de datos: fechas, códigos, nombres, descripciones, salarios, costes, etc. Estos y otros datos se deben de almacenar en el tipo de datos más adecuado. El tipo de dato seleccionado dependerá del tipo de información que se desee almacenar en cada columna.

En el estudio que aquí se realiza lo que tiene importancia es saber si la definición de los campos de las tablas declarados en el código fuente y por tanto admitidos por el gestor de bases de datos Informix-SQL son: por un lado soportados por el driver JDBC de Java que se utiliza como puente para la ejecución de las sentencias SQL y por otro lado compatibles con los tipos de datos definidos en otros gestores de base de datos.

Desafortunadamente hay variaciones significativas entre los tipos de datos SQL soportados por los diferentes gestores de bases de datos. Incluso, para complicar más el estudio, los diferentes gestores soportan algunos tipos de datos que semánticamente son igual pero tienen diferente nombre.

El API JDBC define un conjunto de genérico de tipos de dato SQL en la clase java.sql.Types. Estos tipos fueron diseñados para representar la mayoría de los tipos de datos más comúnmente utilizados. A la hora de hacer la traducción del código fuente, si este se pretende sea valido para cualquier gestor de bases de datos, hay que tener especial cuidado con la definición de los tipos de datos que hace cada gestor ya que los nombres genéricos que define el API JDBC de Java no siempre son soportados por ellos.

Como resultado de estudio se obtendrán los siguientes resultados:

El mapeo entre los tipos de datos de Informix-SQL y el resto de gestores de bases de datos, de los aquí estudiados, con objeto de que las definiciones de los campos de las tablas que aparecen en el código fuente Informix puedan ser ejecutados, aplicando dichos mapeos, sobre cualquiera de los otros gestores de bases de datos. Para realizar este mapeo de forma coherente se realizará un estudio sobre la definición que cada proveedor de bases de datos hace de sus tipos de datos.

La relación que cada proveedor de bases de datos realiza entre sus tipos de datos y los tipos de datos SQL de la API JDBC. Esta relación no nos proporciona directamente información aplicable para la traducción de código fuente Informix a Java pero si nos ayudará, en casos, a clarificar sobre que tipo de dato se puede mapear un tipo de dato Informix-SQL. El observar que en la mapeo que cada proveedor hace entre sus tipos de datos y los datos SQL JDBC nos puede hacer ver que dos proveedores distintivos mapean tipos de datos sintácticamente diferentes contra el mismo tipo de dato SQL JDBC y haciendo un estudio pormenorizado se puede ver que aunque ambos proveedores llamen de diferente forma a un tipo de dato semánticamente son iguales.

Por último, y no por ello menos importante, los métodos que proporciona la API JDBC de Java para transferir datos entre las diferentes bases de datos y las aplicaciones desarrolladas en Java. No solo es preciso saber que métodos aplicar para transferir datos de un campo de una tabla de una base de datos sino sobre que tipo de variables Java se van a almacenar los resultados obtenidos y viceversa.

TIPOS DATOS BASICOS

En primer lugar con objeto de sentar bases sobre los tipos de datos SQL y ayudar en el estudio que aquí se pretende realizar se presenta una tabla con los tipos de datos básicos. Los tipos de datos SQL se clasifican en 13 tipos de datos primarios y de varios sinónimos válidos reconocidos para dichos tipos de datos.

Tipos de datos primarios:

Tipo de Datos Longitud Descripción

BINARY 1 byte Para consultas sobre tabla adjunta de productos de bases de datos que definen un tipo de datos Binario.

Page 155: IfxToJava2

155

BIT 1 byte Valores Si/No ó True/False

BYTE 1 byte Un valor entero entre 0 y 255.

COUNTER 4 bytes Un número incrementado automáticamente (de tipo Long)

CURRENCY 8 bytes Un entero escalable entre 922.337.203.685.477,5808 y 922.337.203.685.477,5807.

DATETIME 8 bytes Un valor de fecha u hora entre los años 100 y 9999.

SINGLE 4 bytes

Un valor en punto flotante de precisión simple con un rango de -3.402823*1038 a �1.401298*10-45 para valores negativos, 1.401298*10-45 a 3.402823*1038 para valores positivos, y 0.

DOUBLE 8 bytes

Un valor en punto flotante de doble precisión con un rango de -1.79769313486232*10308 a -4.94065645841247*10-324 para valores negativos, 4.94065645841247*10-324 a 1.79769313486232*10308 para valores positivos, y 0.

SHORT 2 bytes Un entero corto entre -32,768 y 32,767.

LONG 4 bytes Un entero largo entre -2,147,483,648 y 2,147,483,647.

LONGTEXT 1 byte por carácter

De cero a un máximo de 1.2 gigabytes.

LONGBINARY Según se necesite De cero 1 gigabyte. Utilizado para objetos OLE.

CHARACTER 1 byte por carácter De cero a 255 caracteres.

Tabla 21: Tipos de datos primarios

La siguiente tabla recoge los sinónimos de los tipos de datos definidos:

Tipo de Dato Sinónimos

BINARY VARBINARY

BIT

BOOLEAN LOGICAL LOGICAL1 YESNO

BYTE INTEGER1

COUNTER AUTOINCREMENT

CURRENCY MONEY

DATETIME DATE TIME TIMESTAMP

SINGLE FLOAT4 IEEESINGLE REAL

DOUBLE

FLOAT FLOAT8 IEEEDOUBLE NUMBER NUMERIC

Page 156: IfxToJava2

156

SHORT INTEGER2 SMALLINT

LONG INT INTEGER INTEGER4

LONGBINARY GENERAL OLEOBJECT

LONGTEXT LONGCHAR MEMO NOTE

TEXT

ALPHANUMERIC CHAR CHARACTER STRING VARCHAR

VARIANT (No Admitido) VALUE

Tabla 22: Sinónimos de tipos de datos primarios

TIPOS DE DATOS JDBC

Es importante tener claros los tipos de datos que soporta el API JDBC de Java ya que este va ser el interface que se utilizará para interactuar con las diferentes bases de datos, ósea el puente intermedio entre los valores almacenados en las variables de programa y los campos de las tablas de las bases de datos.

Cada proveedor de bases de datos proporcionará la compatibilidad en la definición de los tipos de datos que soporte su gestor con aquellos que soporte el SQL JDBC de Java. Esta compatibilidad es necesaria por dos motivos: primero los tipos de datos definidos en el API JDBC serán los contenedores intermedios entre los tipos de datos definidos en Java y los definidos en el gestor de bases de datos y segundo el API JDBC proporciona métodos necesarios para manipular los tipos de datos que define en su interface JDBC.

Los tipos de datos soportados por el SQL del interface JDBC de Java (JAVA TM JDBC 2.0 API) son:

JDBC SQL Type Descripción

CHAR Cadena de tamaño fijo de 0 a 254 caracteres de longitud

VARCHAR Cadena de longitud variable de 0 a 254 caracteres de longitud

LONGVARCHAR Cadena de longitud variable de al menos 1 Gb

NUMERIC

Represente un valor decimal de precisión fija. La precisión es el númerototal de dígitos decimales soportados, y la escala es el número dígitos después del punto decimal. JDBC requiere que la precisión y escala pueden tener un valor al menos de 15 dígitos.

DECIMAL Dato equivalente al NUMERIC

BIT Representa un solo bit que puede tomar los valores uno o cero

TINYINT Tipo entero de 8 bits, representa valores entre 0 y 255 con o sin signo

SMALLINT Entero con signo de 16 bits, toma valores entre -32768 and 32767

INTEGER Entero con signo de 32 bits, toma valores entre -2147483648 and 2147483647

BIGINT Entero con signo de 64-bit, admite valores desde -9223372036854775808

Page 157: IfxToJava2

157

hasta 9223372036854775807

REAL Número en punto flotante de simple precisión y al menos 7 dígitos de mantisa

FLOAT Tipo de dato equivalente al DOUBLE

DOUBLE Número en punto flotante de doble precisión que soporta 15 dígitos de mantisa

BINARY Dato de tipo binario de longitud fija de 0 a 254 bytes

VARBINARY Dato de tipo binario de longitud variable de 0 a 254 bytes

LONGVARBINARY Dato de tipo binario que admite al menos 1 Gb de datos

DATE Representa una fecha formada por día, mes, y año

TIME Representa una unidad de tiempo en formato horas, minutos, y segundos.

TIMESTAMP Tipo de dato donde almacenamos fecha y hora hasta una precisión de microsegundos (6 dígitos de precisión).

Tabla 23: Tipos de datos JDBC

Se puede observar que esta tabla se utiliza el término �JDBC SQL type� en lugar de �SQL type�, ambos términos se refieren a los tipos genéricos de SQL definidos en java.sql.Types, y ambos son intercambiables.

Los tipos de datos básicos de JDBC son tipos de datos que se introdujeron en la API principal de Java JDBC 1.0. y se han ido completando y ampliando en versiones sucesivas. Los diferentes controladores JDBC implementados por los proveedores de los respectivos gestores de bases de datos utilizan los tipos de datos básicos de JDBC para convertir los tipos de datos propios definidos por su gestor en un formato comprensible para el lenguaje de programación Java y viceversa.

Cada proveedor proporciona la relación entre los tipos de datos básicos que define en su gestor, JDBC y el lenguaje de programación Java.

Estos tipos de datos:

Soporta los tipos de datos más comunes de SQL, mapeados en forma de tipos de datos Java.

Muchos de los tipos de datos estándar de SQL-92, no tienen un equivalente nativo en Java. Para superar esta deficiencia, se deben mapear los tipos de datos SQL en Java, utilizando las clases JDBC para acceder a los tipos de datos SQL. Es necesario saber cómo recuperar adecuadamente tipos de datos Java; como int, long, o string, a partir de sus contrapartidas SQL almacenadas en base de datos. Esto puede ser especialmente importante si se está trabajando con datos numéricos que necesiten control decimal con precisión, o con fechas SQL, que tienen un formato muy bien definido.

Posibilitan que el mapeo de los tipos de datos Java a SQL es realmente sencillo.

TIPOS DE DATOS INFORMIX-SQL

Los principales tipos de datos soportados por Informix-SQL se pueden agrupar en los siguientes:

CHARACTER

Las columnas tipo carácter almacenan combinaciones de letras números y símbolos. Las columnas tipo char se utilizan normalmente para almacenar nombres, direcciones, números de la seguridad social, nombres de proyectos, etc.

CHAR [ (n) ] Admite letras, números y símbolos. Se puede, opcionalmente, especificar la longitud de la columna tipo carácter, La longitud máxima de las cadenas es de 32767. Sino se indica la longitud de la cadena por defecto se entiende que es 1.

CHARACTER Es un sinónimo de CHAR.

Page 158: IfxToJava2

158

NUMBERICOS

El tipo de dato NUMBER incluye 6 diferentes tipos de datos para almacenar cada diferente tipo de número.

SMALLINT Admite un número entero entre -32,767 y +32,767.

INTEGER Admite un número entero entre -2,147,483,647 y +2,147,483,647.

INT Es un sinónimo de INTEGER.

SMALLFLOAT Representa un número de punto flotante con aproximadamente 7 dígitos significativos.

REAL Es un sinónimo de SMALLFLOAT.

FLOAT Representa un número de punto flotante con aproximadamente 14 dígitos significativos.

DOUBLE PRECISION Es un sinónimo para FLOAT.

DECIMAL [ (m [, n]) ] Define un tipo de dato numérico con precisión y escala fijas. Especificar la precisión y escala es opcional. Sino se indica la precisión por defecto se entiende que ésta es 16, en el caso de la escala el valor por defecto es 0.

DEC y NUMERIC Son dos sinónimo de DECIMAL.

SERIAL

Esta columna almacena números secuenciales generados por el gestor de bases de datos. No se debe de añadir datos en una columna tipo SERIAL, cada vez que se añade una nueva fila a una tabla el gestor automáticamente asigna el siguiente valor numérico de forma secuencial a la columna tipo SERIAL. Normalmente el valor inicial es 1, pero el usuario puede seleccionar el valor inicial mayor de 0 como valor inicial. El valor mayor que admite una columna tipo serial es 2.147.483.647.

Una vez que se asigna un valor a un campo tipo SERIAL este no se puede modificar. Cada tabla de la base datos solo puede tener, como máximo, un campo tipo SERIAL.

SERIAL [ ( n ) ] Define un tipo de dato autoincremental. El valor inicial por defecto es 1, a no ser que se indique explícitamente otro valor entero positivo.

FECHA Y HORA

DATE Tipo de dato que almacena fechas. Una columna tipo DATE almacena fechas en el formato mm/dd/yyyy donde mm es el mes (1-12), dd es el día del mes (1-31), y yyyy es el año (0001-9999).

El formato por defecto es mm/dd/yyyy

Internamente el gestor almacena los campos de tipo DATE como un entero de 4 bytes el cual representa el número de días desde principios del siglo XX, 0 representa el 31 de diciembre de 1899, 1 el 1 de enero de 1900 y así sucesivamente.

DATETIME Columna que contiene valores que representan momentos en el tiempo, su sintaxis se muestra a continuación:

DATETIME {YEAR|MONTH|DAY|HOUR|MINUTE|SECOND|FRACTION} TO {YEAR|MONTH|DAY|HOUR|MINUTE|SECOND|FRACTION}

Una columna de este tipo guarda valores que representan un momento en el tiempo. El momento en el tiempo permite especificar desde año hasta la fracción de segundo. La precisión de una columna de tipo DATETIME se fija en el momento de la definición de la misma y puede llegar a ser hasta de hasta microsegundos (6 dígitos) siendo el valor por defecto de milisegundos (3 dígitos).

El formato de un valor DATETIME es: yyyy-mm-dd hh:mm:ss.fff

Page 159: IfxToJava2

159

MONEDA

MONEY [ (m [, n]) ] Esta columna almacena cantidades monetarias, en la precisión se indican la cantidad monetaria y en la escala los céntimos. Sino se indica, por defecto, la precisión es 16 y la escala 2.

INTERVALOS

INTERVAL Esta columna contiene valores que representan intervalos de tiempo. Su sintaxis se indica a continuación:

INTERVAL { [YEAR (n) | MONTH (n) ] TO [YEAR | MONTH] | [DAY(n)] | HOUR(n) | MINUTE(n) | SECOND(n) | FRACTION(n) TO [DAY | MINUTE | SECOND | FRACTION] }

Este tipo de dato permite almacenar valores que representan un intervalo o periodo de tiempo. Un valor de tipo intervalo puede representar un intervalo de años y meses o un intervalo de días hasta fracciones de segundo. La precisión de una columna de tipo intervalo se establece en el momento de la definición de la misma.

TEXT/BYTE

Esta columna almacena tipos de datos simples de gran longitud. La longitud máxima es de 2**31 bytes.

TEXT Cadena de caracteres de hasta 1 Gb de longitud.

BYTE Cadena de caracteres binarios de hasta 1 Gb de longitud.

Una vez definidos los tipos de datos que soporta el gestor de bases de datos Informix-SQL el paso más delicado para garantizar que la definición que éste hace es compatible con la que hacen el resto gestores de bases de datos aquí estudiados es encontrar, para cada uno, el tipo de dato equivalente semánticamente, para ello se ha de estudiar:

La definición que cada gestor hace de sus tipos de datos.

La relación que cada gestor proporciona entre sus tipos de datos y los tipos de datos genéricos ODBC y que este será el interface entre el lenguaje de programación y el gestor de bases de datos.

Por otro lado no solo se ha de tener en cuenta la definición de los datos por cada gestor de base de datos sino también la manipulación de los mismos.

En la tabla que se muestra a continuación se proporciona la relación entre el tipo de dato definido en Informix-SQL y aquel, correspondiente a la API de JDBC, que permite la manipulación del mismo. Esta asociación ayudará la traducción de los tipos de datos, que aparezcan en las sentencias SQL del código fuente Informix-4GL , a su equivalente de los soportados por el gestor de bases de datos destino en la definición de tablas y el manejo de los datos a través del API JDBC.

Tipo Dato Informix Tipo de valor Almacenado Tipo Dato SQL JDBC

BYTE Cadena binaria de longitud máxima 1 Gb LONGVARBINARY

CHAR | CHARACTER Si cadena de caracteres de hasta 254 caracteres ASCII

CHAR

CHAR | CHARACTER Cadena de caracteres de más de 254 caracteres ASCII

LONGVARCHAR

DATE Fechas desde 31 de diciembre de 1899 DATE

DATETIME year to day Momentos en el tiempo que representan fechas DATE

DATETIME hour to second Momentos en el tiempo que representas horas TIME

Page 160: IfxToJava2

160

DATETIME Punto en el tiempo, especifica fechas combinadas con la hora del día hasta precisión de microsegundos

TIMESTAMP

DEC | DECIMAL | NUMERIC

Número en punto fijo con una precisión máxima de 16 dígitos

DECIMAL

DOUBLE PRECISION | FLOAT

Número en punto flotante de hasta 14 dígitos de precisión.

DOUBLE

INTEGER | INT Entero, desde -2,147,483,647 hasta +2,147,483,647

INTEGER

INTERVAL Intervalos de tiempo no soportado

MONEY Cantidad monetaria definida con escala y precisión

DECIMAL(16,2)

SMALLFLOAT | REAL Número en punto flotante de hasta 7 dígitos de precisión

REAL

SMALLINT Número entero desde -32,767 hasta +32,767 SMALLINT

SERIAL Tipo de dato incremental INTEGER

TEXT Cadena de caracteres de longitud máxima 1 Gb LONGVARCHAR

VARCHAR Cadena de longitud variable y no mas de 255 caracteres

VARCHAR

Tabla 24: Mapeos de datos Informix-SQL a SQL JDBC

Analizando las conversiones aquí plantadas se ve:

El tipo de dato CHAR de Informix-SQL se ha de transformar en un tipo de datos del SQL de JDBC CHAR o en un LONGVARCHAR en función de la longitud con la que se haya definido este tipo de dato en el código fuente. La elección entre un tipo de datos u otro no será complicada ya que en la definición del campo la longitud a de venir expresada como un literal numérico de forma explicita

El tipo de dato TIMESTAMP que representa momentos en el tiempo se puede transformar en un tipo de dato JDBC: DATE, TIME o TIMESTAMP en función de la definición del mismo, esto se puede discernir a la hora de hacer la traducción de código fuente a objeto.

El tipo de datos SERIAL que define el gestor de bases de datos Informix-SQL se representa vía JDBC con un tipo de datos INTEGER lo cual sintácticamente es correcto pero semánticamente no ya que aunque un INTEGER pueda albergar el contenido del tipo de dato SERIAL este último tiene un significado especial para el gestor de bases de datos Informix-SQL que no tiene el tipo de datos INTEGER.

INTERVAL. Este tipo de dato no es soportado por el estándar JDBC 2.0 y en esta versión del traductor no será considerado.

Según la tabla anterior de los tipos de datos que soporta el API JDBC se van a utilizar: LONGVARBINARY, CHAR, LONGVARCHAR, DATE, TIME, TIMESTAMP, DECIMAL, DOUBLE, INTEGER, REAL, SMALLINT, y VARCHAR.

Una vez que tenemos claro que tipo de dato de la API JDBC es capaz de albergar cada tipo de datos que aparecen en las sentencias Informix-SQL esto nos asegura que esos tipos de datos podrán ser manejados sin problemas en el código destino, JAVA, a través del dicha API. El hecho de saber el mapeo que hacen el resto de gestor de bases de datos entre sus tipos de datos y los proporcionados por el driver JDBC nos proporcionará información adicional que en ciertos casos nos puede ser de utilidad.

Page 161: IfxToJava2

161

TIPO DE DATOS SQLSERVER

El gestor de bases de datos SqlServer soporta los siguientes tipos de datos:

ENTEROS

BIT Datos enteros con valor 1 ó 0.

INT Datos enteros (números enteros) comprendidos entre -231 (-2.147.483.648) y 231 - 1 (2.147.483.647).

INTEGER es un sinónimo para INT.

SMALLINT datos enteros comprendidos entre 215 (-32.768) y 215 - 1 (32.767).

TINYINT Datos enteros comprendidos 0 y 255.

BIGINT Datos enteros (números enteros) comprendidos entre -263 (-9.223.372.036.854.775.808) y 263 -1 (9.223.372.036.854.775.807). El tamaño de almacenamiento es 8 bytes.

DECIMALES Y NUMÉRICOS

DECIMAL [ ( p [, s] ) ] Números de precisión y escala fijas. Cuando se utiliza la precisión máxima, los valores permitidos están comprendidos entre - 1038 +1 y 1038 - 1.

NUMERIC y DEC Son sinónimo de DECIMAL.

MONEY Y SMALLMONEY

MONEY Valores de moneda comprendidos entre -263 (-922.337.203.685.477,5808) y 263 - 1 (+922.337.203.685.477,5807), con una precisión de una diezmilésima de la unidad monetaria.

SMALLMONEY Valores de moneda comprendidos entre -214.748,3648 y +214.748,3647, con una precisión de una diezmilésima de la unidad monetaria.

NUMÉRICOS CON APROXIMACIÓN

FLOAT [ ( n ) ] Un número de punto flotante con los siguientes valores válidos: de - 1.79E + 308 a -2.23E - 308, 0 y de 2.23E -308 a 1.79E + 308. n es el número de bits que se utilizan para almacenar la mantisa del número FLOAT en notación científica y por tanto dicta su precisión y el tamaño de almacenamiento. n tiene que ser un valor entre 1 y 53. El valor predeterminado de n es 53.

REAL Datos numéricos de punto flotante con los siguientes valores válidos: de �3.40E + 38 a -1.18E - 38, 0 y de 1.18E - 38 a 3.40E + 38. El tamaño de almacenamiento es 4 bytes.

En SqlServer, el sinónimo de REAL es FLOAT(24).

DATETIME Y SMALLDATETIME

DATETIME Datos de fecha y hora comprendidos entre el 1 de enero de 1753 y el 31 de diciembre de 9999 con una precisión de un trescientosavo de segundo, o 3.33 milisegundos. Para representar este tipo de datos internamente SqlServer utiliza una cadena de 8 bytes: los 4 primeros representan el número de días desde (o antes de) el 1 de enero de 1900 y los cuatro segundos representan el número de milisegundos desde la medianoche.

SMALLDATETIME Datos de fecha y hora comprendidos entre el 1 de enero de 1900 y el 6 de junio de 2079 con una precisión de un minuto. La representación interna de este tipo de dato es mediante 4 bytes, los dos primeros representan el número de días desde el 1 de enero de 1900 y los dos segundos los minutos desde la media noche.

NUMÉRICOS

CURSOR Un tipo de datos para las variables o para los parámetros de resultado de los procedimientos almacenados que contiene una referencia a un cursor. Las variables creadas con el tipo de datos CURSOR aceptan Null.

Page 162: IfxToJava2

162

TIMESTAMP Es un tipo de datos que expone automáticamente números binarios generados, cuya exclusividad está garantizada en la base de datos. TIMESTAMP se suele utilizar como mecanismo para marcar la versión de las filas de la tabla. El tamaño de almacenamiento es de 8 bytes.

El tipo de datos TIMESTAMP de Transact-SQL no es el mismo que el tipo de datos TIMESTAMP definido en el estándar SQL-92. El tipo de datos TIMESTAMP de SQL-92 es equivalente al tipo de datos DATETIME Transact-SQL

ROWVERSION Es un sinónimo de TIMESTAMP.

UNIQUEIDENTIFIER Un identificador exclusivo global (GUID).

CADENAS DE CARACTERES

CHAR [ (n) ] Datos de caracteres no Unicode de longitud fija con una longitud máxima de 8.000 caracteres. El tamaño de almacenamiento es n bytes, la longitud por defecto es 1.

CHARACTER es un sinónimo de CHAR

VARCHAR [ (n) ] Datos de caracteres no Unicode de longitud variable con una longitud de n bytes. n tiene que ser un valor comprendido entre 1 y 8.000. Cuando no se especifica el argumento n en una instrucción de definición de datos o de declaración de variable, la longitud predeterminada es 1.

CHAR VARYING y CHARACTER VARYING son sinónimos de VARCHAR.

TEXT Datos no Unicode de longitud variable con una longitud máxima de 231 - 1 (1.147.483.647) caracteres.

CADENAS DE CARACTERES UNICODE

NCHAR [ (n) ] Datos Unicode de longitud variable con una longitud máxima de 4.000 caracteres. El tamaño de almacenamiento es dos veces n bytes. Si no se especifica longitud por defecto se entiende que es 1.

NATIONAL CHAR y NATIONAL CHARACTER son sinónimos de NCHAR.

NVARCHAR [ (n) ] Datos Unicode de longitud variable con una longitud máxima de 4.000 caracteres. El tamaño de almacenamiento, en bytes, es dos veces el número de caracteres especificados. Si no se especifica longitud por defecto se entiende que es 1.

NATIONAL CHAR VARYING y NATIONAL CHARACTER VARYING son sinónimos de NVARCHAR.

NTEXT Datos Unicode de longitud variable con una longitud máxima de 230 - 1 (1.073.741.823) caracteres.

CADENAS BINARIAS

BINARY [ ( n ) ] Datos binarios de longitud fija con una longitud máxima de 8.000 bytes. Sino se especifica longitud por defecto ésta es 1. Se utiliza BINARY cuando las entradas de datos de una columna se espera que tengan un tamaño uniforme.

VARBINARY [ ( n ) ] Datos Unicode de longitud variable con una longitud máxima de 8.000 bytes. Sino se especifica longitud por defecto ésta es 1. Se utiliza VARBINARY cuando las entradas de datos de una columna no vayan a tener un tamaño uniforme.

IMAGE Datos Unicode de longitud variable con una longitud máxima de 231 - 1 (1.147.483.647) bytes.

Page 163: IfxToJava2

163

Los tipos de datos soportados por SqlServer son mucho más ricos, tanto en variedad como en rangos que soportan, que los que admite la versión de Informix-SQL que aquí se estudia, quizá debido a que la versión de SqlServer es más moderna. Esto facilitará el que los tipos de datos definidos en Informix-SQL sean también admitidos por SqlServer. Como ejemplos el tipo de dato BIGINT definido en SqlServer, Informix-SQL no lo contempla, ocurre lo mismo con el TYNYINT. Los tipos de datos REAL y FLOAT están definidos en ambos gestores pero sin embargo la precisión que admite SqlServer es mucho mayor que la que admite Informix-SQL 38 y 308 frente a 7 y 15.

Según la información proporcionada por el proveedor de driver JDBC para SqlServer, Microsoft, la compatibilidad de los tipos de dato definidos por el gestor con los soportados por el SQL JDBC se muestran en la siguiente tabla:

Tipo Dato SQL Server Tipo Dato SQL JDBC

BINARY BINARY

BIT BIT

CHAR CHAR

DATETIME TIMESTAMP

DECIMAL DECIMAL

DECIMAL() IDENTITY DECIMAL

FLOAT FLOAT

IMAGE LONGVARBINARY

INT INTEGER

INT IDENTITY INTEGER

MONEY DECIMAL

NCHAR CHAR

NTEXT LONGVARCHAR

NUMERIC NUMERIC

NUMERIC() IDENTITY NUMERIC

NVARCHAR VARCHAR

REAL REAL

SMALLDATETIME TIMESTAMP

SMALLINT SMALLINT

SMALLINT IDENTITY SMALLINT

SMALLMONEY DECIMAL

SYSNAME VARCHAR

TEXT LONGVARCHAR

TIMESTAMP BINARY

Page 164: IfxToJava2

164

TINYINT TINYINT

TINYINT IDENTITY TINYINT

UNIQUEIDENTIFIER CHAR

VARBINARY VARBINARY

VARCHAR VARCHAR

BIGINT BIGINT

BIGINT IDENTITY BIGINT

SQL_VARIANT VARCHAR

Tabla 25: Mapeo de tipos de datos SqlServer a SQL JDBC

Viendo esta relación y la de la Tabla 24: Mapeos de datos Informix-SQL a SQL JDBC se puede notar que los tipos de datos Informix-SQL tienen su equivalente dentro de los tipos de datos SqlServer, cabe destacar:

El tipo de dato CHAR de Informix-SQL admite 32767 de longitud mientras que este tipo en SqlServer tiene un tamaño máximo de 8000 caracteres. Esto se tendrá en cuenta a la hora crear tablas en SqlServer, utilizando el tipo de dato TEXT si la definición supera los 8000 caracteres, y a la hora de manipular los datos de las tablas ya que este mismo tipo de dato en el SQL de la API JDBC solo soporta 254 caracteres, en este caso se trabajará con el tipo de dato LONGVARCHAR.

El tipo de datos BYTE de Informix-SQL no existe como tal en SqlServer, pero si existe el tipo de dato IMAGE que semánticamente representa lo mismo. A la hora de definir un campo de una tabla de tipo BYTE para SqlServer se creará como IMAGE, aunque durante la manipulación a través del API JDBC este se tratará como LONGVARCHAR ya que ambos proveedores de mapean el tipo de dato propio del gestor en el tipo de dato del SQL JDBC LONGVARCHAR.

SqlServer no define los tipos de datos DATE y TIME, solo trabaja con el tipo DATETIME. Si en el código fuente se define un campo de una tabla de alguno de los mencionados tipos en el código objeto se crearán como DATETIME ya que este tipo de dato es capaz de albergar la información de cualquiera de los dos anteriores. Así mismo a la hora de manipularlos se tratarán con el tipo de dato del SQL JDBC TIMESTAMP.

El tipo de datos DATETIME de SqlServer admite un rango de fechas inferior al que soporta el tipo de dato DATE de Informix-SQL. El tratamiento de ese problema es algo que excede éste estudio ya que no se pretende hacer un traspaso de datos entre gestores sino que el código fuente que se puede ejecutar sobre el gestor de bases de datos Informix se pueda ejecutar sobre el resto.

Los tipos de datos SERIAL e INTERVAL no existe como tal en SqlServer y, aunque el tipo de dato SERIAL se podría representar como un entero su semántica, número entero autoincremental, no es implementada por el gestor de bases de datos SqlServer. Estos dos tipos de datos se excluirán de este estudio.

TIPOS DE DATOS DE ORACLE

Los tipos de datos definidos por el gestor de bases de Oracle son:

CADENAS DE CARACTERES

CHAR [ (n) ] Define una cadena de ancho fijo. El mayor tamaño admitido es de hasta 2000 bytes. Sino se especifica la longitud por defecto se entiende que tiene un solo carácter (1 byte).

NCHAR [ (n) ] Define una cadena de ancho fijo. El mayor tamaño admitido es de hasta 2000 bytes o caracteres, admite el juego de caracteres NLS y el tamaño de la cadena dependerá del número

Page 165: IfxToJava2

165

de caracteres que tenga y el número de bytes que ocupe cada uno de ellos. Sino se especifica la longitud por defecto se entiende que tiene un solo carácter (1 byte).

VARCHAR [ (n) ] Cadena de caracteres de ancho variable y longitud máxima de 4000 bytes. Se debe especificar el tamaño de la cadena en el momento de la definición.

NVARCHAR [ (n) ] Cadena de caracteres de ancho variable y longitud máxima de 4000 bytes o caracteres. El tamaño es determinado en función del número de bytes requeridos para almacenar cada carácter y el número de estos. Admite el juego de caracteres NLS. Se debe especificar el tamaño en el momento de la definición.

LONG Cadena de ancho variable y hasta un máximo de 2 Gb. Oracle recomienda no usar este tipo de dato.

NUMERICOS

NUMBER [ (p,s) ] Variable numérica definida con precisión y escala. La precisión tiene un rango de 1 a 38 y la escala de -84 a 127.

NUMERIC, DEC, y DECIMAL son sinónimos de NUMBER.

Oracle soporta los tipos de datos: int, integer, smallint float, double precisión, real, etc. aunque internamente los representa como NUMBER, siguiendo la siguiente tabla:

Tipo de dato Representación

DECIMAL, DEC NUMBER

NUMERIC NUMBER

INTEGER NUMBER

INT NUMBER

TINYINT NUMBER

SMALLINT NUMBER(38)

BIGINT NUMBER

FLOAT NUMBER

DOUBLE PRECISION NUMBER

REAL NUMBER

Tabla 26: Tipos de datos numéricos de Oracle

BINARIOS

RAW (n) Cadenas binarias de longitud variable hasta un máximo de 2000 bytes.

LONGRAW Cadenas binarias de longitud variable hasta un máximo de 2 Gb.

BLOB Localizadores LOB apuntan a un gran objeto binario, de hasta un máximo de 4Gb, dentro de la base de datos.

CLOB Localizadores LOB apuntan a un gran objeto de tipo carácter, de hasta un máximo de 4Gb, dentro de la base de datos .

NCLOB Localizadores LOB apuntan a un gran objeto NLS de caracteres, de hasta un máximo de 4Gb, dentro de la base de datos

BFILE Localizadores de archivo apuntan a un objeto binario de sólo lectura fuera de la base de datos. Longitud máxima 4 Gb.

Page 166: IfxToJava2

166

DATETIME

DATE Una fecha entre el 1 de Enero de 4712 A.C. y el 31 de Diciembre de 9999 D.C. Representa fechas con el formato: DD-MON-YYYY HH{A|P}M :MI:SS. Oracle representa internamente las fechas como una cadena de 7 bytes: el primero representa la centuria + 100, el segundo del año + 100, el tercero el mes, el cuarto el día del mes, el quinto la hora + 1, el sexto el minuto +1 y el séptimo el segundo +1.

TIMESTAMP Oracle expande el tipo de dato DATE con este tipo de dato el cual almacena la misma información y además las fracciones de segundo hasta con una precisión de 10 dígitos (por defecto 6 dígitos). El formato de este campo es: DD-MON-YYYY HH:MI:SS.FFFFFFFFFF {A|P}M

Oracle admite también los tipos de datos: TIMESTAMP WITH TIMEZONE y TIMESTAMP WITH LOCAL TIMEZONE con las mismas características que el tipo de dato TIMSTAMP pero teniendo en cuenta el horario en función de la zona horaria y en función de la zona horaria local.

INTERVALOS

INTERVAL DAY TO SECOND, formato: DD HH MI SS, campo de tamaño fijo que representa un periodo de tiempo que incluye: días, horas, minutos y segundos

INTERVAL YEAR TO MONTH, formato: YYYY MM, campo de tamaño fijo que represente un periodo de tiempo en años y meses.

ROWS

ROWID tipo de dato binario que es utilizado para identificar una fila.

UROWID universal rowid, es un tipo de dato utilizado para almacenar el rowid físico y el lógico cuando las tablas son accedidas a través de un gateway.

Definidos los tipos de datos principales de Oracle es necesario conocer como el JDBC, proporcionado por Oracle, contempla cada uno de ellos a la hora de hablar con el gestor de bases de datos.

En la siguiente tabla se muestra en resumen como realiza Oracle el mapeo de sus tipos de datos SQL vía JDBC:

Tipo Dato Oracle Tipo Dato SQL JDBC

CHAR CHAR

VARCHAR VARCHAR

LONG | CLOB LONGVARCHAR

NUMBER NUMERIC

NUMBER DECIMAL

NUMBER BIT

NUMBER TINYINT

NUMBER SMALLINT

NUMBER INTEGER

NUMBER BIGINT

NUMBER REAL

NUMBER FLOAT

NUMBER DOUBLE

NUMBER BINARY

Page 167: IfxToJava2

167

RAW VARBINARY

LONGRAW | BLOB LONGVARBINARY

DATE DATE

DATE TIME

TIMESTAMP TIMESTAMP

Tabla 27: Mapeo de tipos de datos Oracle a SQL JDBC

Viendo los tipos de datos que define Oracle puede parecer complicado la transformación de las sentencias SQL de creación de tablas de Informix a Oracle ya que el primero define muchos más tipos de datos numéricos, pero la Tabla 27: Mapeo de tipos de datos Oracle a SQL JDBC nos hace ver que todo tipo numérico se representa en Oracle como NUMBER independientemente de su rango con lo cual el código generado para ser ejecutado contra el gestor de bases de datos Oracle solo considerará dicho tipo numérico.

Otro elementos que entran en consideración sobre los tipos de datos Oracle son:

No contempla los tipos de datos INTERVAL y SERIAL al igual que pasaba con SqlServer. El tipo de datos INTERVAL si es definido en oracle, pero no es contemplado en la implementación del JDBC definido por el mismo lo cual imposibilita, en primera instancia, la manipulación de este dato.

No define el tipo de dato MONEY, pero como su semántica es igual a la de un tipo de datos DECIMAL(16,2) el cual si es contemplado por Oracle no habría ningún problema en tratar estos tipos de datos en este gestor tanto en la definición como en la manipulación.

Aparentemente no soporta el tipo de dato BYTE de Informix-SQL, pero define el tipo de dato LONGRAW que semánticamente es igual con lo cual a la hora de definir campos de tablas si en el fuente aparece el un tipo de datos BYTE se traducirá en LONGRAW. La manipulación del ambos por el API JDBC es a través del tipo LONGVARCHAR.

Los tipos de datos de Informix-SQL TEXT y CHAR de longitud superior a 254 caracteres tienen su equivalente en el tipo de dato LONG de Oracle.

El tipo de dato DATE es capaz de albergar, en base a su definición fechas y horas con lo que los tipos de datos TIME y DATE de Informix-SQL se mapearán en este.

TIPOS DE DATOS DE DB2

Tipos de datos admitidos por DB2 en la creación de tablas se clasifican en los siguiente grupos:

CADENAS DE CARACTERES

CHAR(n) especifica una cadena n de caracteres de tamaño fijo. La longitud máxima es de 254 caracteres.

VARCHAR(n) cadena de tamaño variable de hasta un máximo de 32672 caracteres.

GRAPHIC

Estos tipos de datos son utilizados para almacenar gráficos. El tipo GRAPHIC es una secuencia de bytes que representan datos de tipo carácter de double-bytes. La longitud es el número de double-bytes consecutivos reservados.

GRAPHIC(n) es una cadena gráfica de tamaño fijo y un máximo de 127 double-bytes. Si no se especifica n por defecto es 1.

VARGRAPHIC(n) Cadena gráfica de tamaño variable. El rango de n va desde 1 hasta 16336 double-byte.

Page 168: IfxToJava2

168

NUMERICOS

SMALLINT es una variable de 2 bytes con una precisión de 5 dígitos. El rango varía desde -32768 hasta 32767.

INTEGER | INT entero de 4 bytes y una precisión de 10 dígitos. El rango va desde -2147483648 hasta +2147483647.

REAL | FLOAT(n) especifica un número en punto flotante de simple precisión, si no se indica el valor de n o es menor de 21 entonces se trata de simple precisión, los valores pueden variar desde 7.2E+75 hasta 7.2E+75.

FLOAT(n) | DOUBLE PRECISION | FLOAT | DOUBLE especifica un número en punto flotante con doble precisión, n puede oscilar entre 22 y 53. Si n se omite por defecto toma el valor de 53. El rango de esta variable va desde 2.225E-307 hasta 1.79769E+308

DECIMAL(p,s) | DEC(p,s) esta variable contiene un valor decimal especificado a través de su precisión y escala, el máximo valor de precisión es de 31 dígitos y el valor de la escala oscila entre cero y la precisión.

DATE, TIME, AND TIMESTAMP

DATE almacena información de fechas (año, mes, y día). El rango que soporta va desde 1 de enero de 0001 hasta 31 de diciembre de 9999. Este tipo de dato es representado internamente por DB2 como una cadena de 4 bytes. Cada byte representa 2 dígitos. Los dos primeros representan el año (de 0001 a 9999), el tercero se reserva para el mes (de 1 a 12) y el cuarto contiene el día (de 1 a 31).

TIME almacena información de horas (hora, minutos, y segundos). El rango que admite va desde las 00 horas 00 minutos 00 segundos hasta 24 horas 00 minutos 00 segundos. La representación interna que hace DB2 de este dato es una cadena de tres bytes, un byte para las horas, otro para los minutos y el último para los segundos.

TIMESTAMP este tipo de dato contiene información de la fecha y la hora hasta un precisión de milisegundos (año, mes, día, hora, minutos, segundos, y microsegundos). El rango que admite vas desde 1 de enero de 0001 a las 00 horas 00 minutos 00 segundos 000000 microsegundos hasta el 31 de diciembre de 9999 a las 24 horas 00 minutos 00 segundos 000000 microsegundos. La representación interna de este tipo de dato es mediante una cadena de 10 bytes: 4 para la fecha, 3 para la hora y los otros tres para representar los microsegundos.

BLOB, CLOB AND DBCLOB

BLOB(n[K|M|G]) tipo de dato que define un objeto binario largo de longitud variable hasta un máximo de 2 Gb. Si solo se especifica el valor de n este indica la longitud máxima. Si K, M, o G son especificados estos pueden ser como máximo: 1024, 1048576 o 1073741824 y n podrá valer como máximo: 2097152, 2048 o 2 respectivamente.

CLOB(n[K|M|G]) cadena de caracteres de tamaño variable y de hasta un máximo de 2 Gb. de longitud.

DBCLOB(n[K|M|G]) objeto de tamaño variable que almacena cadenas de caracteres gráficos de tamaño double-byte. La longitud máxima es de 1073823 caracteres de longitud.

VALORES ROW ID

Los valores ROWID son valores que identifican unívocamente una fila en una tabla. Cada valor en una columna ROWID debe de ser único, cuando una fila es insertada en una tabla, DB2 genera el valor de la columna ROWID amenos que este sea proporcionado. Si el valor ROWID es proporcionado a de ser un valor valido. No se pueden modificar, por el usuario, el valor de una columna tipo ROWID.

En la siguiente tabla se muestran los tipos de datos de DB2 y su correspondiente JDBC:

Tipo de dato DB2 Tipo dato SQL JDBC

SMALLINT BIT, TINYINT, SMALLINT

Page 169: IfxToJava2

169

INTEGER INTEGER

REAL FLOAT, REAL

DOUBLE DOUBLE

DECIMAL NUMERIC, DECIMAL

CHAR CHAR

GRAPHIC CHAR

VARCHAR VARCHAR, LONGVARCHAR

VARGRAPHIC VARCHAR

CLOB(n) VARCHAR, LOGVARHAR, CLOB

BINARY BINARY

VARBINARY VARBINARY

BLOB(n) VARBINARY, LONGVARBINARY

DATE DATE

TIME TIME

TIMESTAMP TIMESTAMP

BLOB BLOB

CLOB CLOB

DBCLOB CLOB

Tabla 28: Mapeo de tipos de datos DB2 a SQL JDBC

Como se ve algún tipo de datos SQL de DB2 se puede convertir en más de uno JDBC esto se entiende desde dos puntos de vista: algunos de los tipos de datos JDBC son sinónimos como el caso de DECIMAL y NUMERIC y en otros casos el tipo de datos DB2 en función de su longitud se podrá convertir en uno u otro de los tipos de datos JDBC.

A la hora de convertir los tipos de datos Informix-SQL a DB2 nos encontramos los mismos problemas que ocurrían con Oracle y también con la misma solución para los casos en los que la hay.

TABLA DE MAPEOS

Del estudio realizado en los puntos anteriores en el que se muestran los tipos de datos soportados por el API JDBC de Java, los definidos por cada uno de los diferentes gestores de bases de datos, y la implementación que cada proveedor de base hace del JDBC así se obtienen las dos tablas que se muestran a continuación:

La primera se centra encontrar los mapeos adecuados que garanticen que las definiciones de datos que se hace en el código fuente Informix-SQL, y por tanto validas para se ejecutadas contra el gestor de bases de datos Informix, puedan ser ejecutadas contra el resto de gestores de bases de datos haciendo para ello las modificaciones oportunas en el código generado. Estos mapeos permitirán que las sentencias de definicion de datos: create, alter, etc. puedan ser ejecutadas contra cualquier gestor de bases de datos de forma transparente e independiente a su definición.

La segunda muestra los mapeos entre los tipos de datos Informix-SQL y los tipos de datos SQL JDBC y la correlación con los mapeos que hace el resto de proveedores de bases de datos con los tipos de datos SQL JDBC. Esta segunda tabla es la que nos permitirá saber como manipular los datos en las sentencias SQL de forma independiente a la definición del mismo que se hace en cada gestor.

Page 170: IfxToJava2

170

Tipo Dato Informix Tipo Dato

JDBC Informix Tipo Dato

SQLSERVER Tipo Dato

Oracle Tipo Dato DB2

BYTE LONGVARBINARY IMAGE LONGRAW |BLOB BLOB

CHAR | CHARACTER (254) CHAR (254) CHAR (8000) CHAR(2000) CHAR (254)

CHAR | CHARACTER (35767) LONGVARCHAR TEXT (2 Gb) LONG ( 2 Gb) VARCHAR (35767)

DATE DATE DATETIME DATE DATE

DATETIME year to day DATE DATETIME DATE DATE

DATETIME hour to second TIME DATETIME DATE TIME

DATETIME TIMESTAMP DATETIME TIMESTAMP TIMESTAMP

DEC | DECIMAL | NUMERIC DECIMAL DECIMAL DECIMAL DECIMAL

DOUBLE PRECISION | FLOAT FLOAT FLOAT FLOAT FLOAT

INTEGER | INT INTEGER INTEGER INTEGER INTEGER

INTERVAL no soportado ---------- ---------- ----------

MONEY DECIMAL DECIMAL DECIMAL DECIMAL

SMALLFLOAT | REAL REAL REAL REAL REAL

SMALLINT SMALLINT SMALLINT SMALLINT SMALLINT

SERIAL INTEGER INTEGER INTEGER INTEGER

TEXT (2 Gb) LONGVARCHAR TEXT (2 Gb) CLOB (4 Gb) CLOB (2 Gb)

VARCHAR (254) VARCHAR VARCHAR(8000) VARCHAR(4000) VARCHAR (4000)

Tabla 29: Mapeo entre tipos de datos Informix-SQL y el resto de gestores

Tipo Dato Informix Tipo Dato

JDBC Informix Tipo Dato JDBC

SQLSERVER Tipo Dato

JDBC Oracle Tipo Dato JDBC

DB2

BYTE LONGVARBINARY LONGVARBINARY LONGVARBINARY LONGVARBINARY

CHAR | CHARACTER CHAR CHAR CHAR CHAR

CHAR | CHARACTER LONGVARCHAR LONGVARCHAR LONGVARCHAR LONGVARCHAR

DATE DATE TIMESTAMP DATE DATE

DATETIME year to day DATE TIMESTAMP DATE DATE

DATETIME hour to second TIME TIMESTAMP TIME TIME

DATETIME TIMESTAMP TIMESTAMP TIMESTAMP TIMESTAMP

DEC | DECIMAL | NUMERIC DECIMAL DECIMAL DECIMAL DECIMAL

DOUBLE PRECISION | FLOAT FLOAT FLOAT FLOAT FLOAT

INTEGER | INT INTEGER INTEGER INTEGER INTEGER

INTERVAL no soportado ---------- ---------- ----------

MONEY DECIMAL DECIMAL DECIMAL DECIMAL

SMALLFLOAT | REAL REAL REAL REAL REAL

Page 171: IfxToJava2

171

SMALLINT SMALLINT SMALLINT SMALLINT SMALLINT

SERIAL INTEGER INTEGER IDENTITY INTEGER INTEGER

GENERATED AS IDENTITY

TEXT LONGVARCHAR LONGVARCHAR LONGVARCHAR LONGVARCHAR

VARCHAR VARCHAR VARCHAR VARCHAR VARCHAR

Tabla 30: Mapeos de datos Informix-SQL a implementaciones JDBC de los gestores

A continuación se mostrará un ejemplo ilustrativo de cómo se generará el código objeto, a partir de la definición de tablas, para cada uno del gestores de base de datos sobre el cual se pueda ejecutar una aplicación:

Código fuente Informix: create table tabla99 (

campo1 byte, campo2 char, campo3 char(10), campo4 char(9000), campo5 date, campo6 datetime year to day, campo7 datetime hour to second, campo8 datetime year to second, campo9 decimal, campo10 decimal(10), campo11 decimal(10,2), campo12 float, campo13 integer, campo14 money, campo15 real, campo16 smallint, campo17 text, campo18 varchar(30)

)

Código objeto generado para ejecutarse contra gestor de base de datos Informix:

create table tabla99 ( campo1 byte , campo2 char(1) , campo3 char(10) , campo4 char(9000) , campo5 date , campo6 date , campo7 datetime hour to second , campo8 datetime year to second , campo9 decimal(16,0) , campo10 decimal(10,0) , campo11 decimal(10,2) , campo12 float , campo13 integer , campo14 decimal(16,2) , campo15 real , campo16 smallint , campo17 text , campo18 varchar(30) )

Código objeto generado para ejecutarse contra gestor de base de datos SqlServer:

create table tabla99 ( campo1 image , campo2 char(1) , campo3 char(10) , campo4 text , campo5 datetime ,

Page 172: IfxToJava2

172

campo6 datetime , campo7 datetime , campo8 datetime , campo9 decimal(16,0) , campo10 decimal(10,0) , campo11 decimal(10,2) , campo12 float , campo13 integer , campo14 decimal(16,2) , campo15 real , campo16 smallint , campo17 text , campo18 varchar(30) )

Código objeto generado para ejecutarse contra gestor de base de datos Oracle:

create table tabla99 ( campo1 blob , campo2 char(1) , campo3 char(10) , campo4 long , campo5 date , campo6 date , campo7 date , campo8 timestamp , campo9 decimal(16,0) , campo10 decimal(10,0) , campo11 decimal(10,2) , campo12 float , campo13 integer , campo14 decimal(16,2) , campo15 real , campo16 smallint , campo17 clob , campo18 varchar(30) )

Código objeto generado para ejecutarse contra gestor de base de datos Db2:

create table tabla99 ( campo1 blob , campo2 char(1) , campo3 char(10) , campo4 long varchar , campo5 date , campo6 date , campo7 time , campo8 timestamp , campo9 decimal(16,0) , campo10 decimal(10,0) , campo11 decimal(10,2) , campo12 float , campo13 integer , campo14 decimal(16,2) , campo15 real , campo16 smallint , campo17 clob , campo18 varchar(30) )

Dentro del Anexo I se pueden ver ejemplos prácticos, de traducción de código fuente a objeto, de la creación de una tabla en la que intervienen todos los tipos de datos. Dirigirse al apartado: Ejemplo sentencia tipos de datos.

MAPEO DE TIPOS DE DATOS ENTRE JDBC Y JAVA Ya hemos definido los mapeos entre Informix-SQL y el resto de gestores de bases de datos necesario para la creación de tablas en cada gestor de bases de datos, también se han mostrado la tabla de mapeos de todos los gestores con el SQL JDBC interface que se utilizará para la

Page 173: IfxToJava2

173

manipulación de los datos entre el lenguaje de programación y el gestor de bases de datos. Ahora lo que nos queda es saber que tipo de dato Java se utilizará como contenedor inicial o final de los datos utilizados o retornados de la ejecución de una sentencia SQL. Para ello se ha de definir el mapeo entre los tipos de dato SQL JDBC y Java y viceversa.

El interface JDBC proporciona un mapeo razonable de los tipos de datos SQL más comunes a Java. En los puntos anteriores hemos obtenido la suficiente información sobre los tipos de datos de los diferentes gestores como para poder garantizar que las tareas de almacenar y obtener parámetros y recuperar resultados de las sentencias SQL sean posibles de forma segura.

En la tabla que se muestra a continuación se muestran los mapeos de los tipos de datos SQL JDBC definidos en la Tabla 30: Mapeos de datos Informix-SQL a implementaciones JDBC de los gestores a los tipos de datos Java.

Tipo de dato SQL JDBC Tipo de dato Java

CHAR String

VARCHAR String

LONGVARCHAR String

NUMERIC | DECIMAL java.math.BigDecimal

SMALLINT short

INTEGER int

REAL float

FLOAT double

DOUBLE double

LONGVARBINARY byte[]

DATE java.sql.Date

TIME java.sql.Time

TIMESTAMP java.sql.Timestamp

Tabla 31: Mapeo entre tipos de datos SQL JDBC y Java

En la siguiente tabla se muestra el mapeo inverso al mostrado en la tabla anterior:

Tipo de dato Java Tipo de dato SQL JDBC

String VARCHAR o LONGVARCHAR

java.math.BigDecimal NUMERIC | DECIMAL

short SMALLINT

int INTEGER

float REAL

Double DOUBLE

byte[] VARBINARY o LONGVARBINARY

java.sql.Date DATE

Page 174: IfxToJava2

174

java.sql.Time TIME

java.sql.Timestamp TIMESTAMP

Tabla 32: Mapeo entre tipos de datos Java y SQL JDBC

FUNCIONES DE RECUPERACION DE DATOS SQL Para recuperar datos SQL de una tabla de una base de datos lo primero que debemos saber es el tipo de dato a recuperar, y esto lo podríamos saber de varias formas:

En la definición de la tabla podemos guardar el tipo de dato de cada columna. Esto solo nos vale si en el programa actual trabajamos con una tabla que hemos creado en el mismo.

A través del dato sobre el cual se va a almacenar el resultado. Es un método bastante bueno pero impreciso.

La mejor solución es consultar al propio gestor de bases de datos de que tipo de dato es el campo que se pretende recuperar.

La API JDBC de Java proporciona en su clase ResultSet métodos suficientes para recuperar los datos SQL de una base de datos. JDBC permite muchas lateralidades para utilizar los métodos getXXX para obtener diferentes tipos de datos SQL, por ejemplo, el método getInt puede ser utilizado para recuperar cualquier tipo numérico de caracteres. Los datos recuperados serán convertidos a un int; esto es, si el tipo SQL es VARCHAR, JDBC intentará convertirlo en un entero. Lo ideal es utilizar cada método para recuperar el tipo de dato para el cual fue diseñado, esto no implica que un mismo método pueda ser utilizado para recuperar distintos tipos de datos SQL, por ejemplo el método getString es el adecuado para recuperar campos de los tipos de datos CHAR, VARCHAR e incluso LONGVARCHAR.

Java proporciona es su documentación relativa a la API JDBC una tabla con todas las posibilidades de método a aplicar para recuperar cada tipo de datos SQL. En la tabla que hay a continuación muestra el método más adecuado para recuperar tipos SQL JDBC.

Tipo de dato SQL JDBC Función Java para recuperarlo

CHAR GetString

VARCHAR GetString

LONGVARCHAR GetAsciiStream, getCharacterStream, getString

NUMERIC | DECIMAL GetBigDecimal, getDouble

SMALLINT GetShort

INTEGER GetInt

REAL GetFloat

FLOAT GetDouble

DOUBLE GetDouble

LONGVARBINARY GetBinaryStream

DATE GetDate

TIME GetTime

Page 175: IfxToJava2

175

TIMESTAMP GetTimestamp

Tabla 33: Funciones para recuperación de datos del gestor de bases de datos

CONVERSIONES DE TIPOS DE DATOS En general los valores son representados por algún tipo de dato. Cada tipo de dato describe que tipo de información almacena y que tipo de operaciones se pueden hacer sobre el mismo. En algunos casos un valor almacenado en un tipo de dato puede convertirse en otro.

En este punto se trata:

Describir las conversiones automáticas o implícitas que son soportadas por el gestor de bases de datos Informix con el objeto de saber si aquellas que se hayan aplicado en el código fuente pueden ser mantenidas en el código destino y por tanto ejecutadas sobre otros gestores de bases de datos sin generar ningún error de ejecución.

Reconocer aquellas conversiones que siendo tratadas como implícitas en el gestor de bases de datos origen en el destino no lo son, son explicitas, y en tal caso aplicar las medidas necesarias a la hora de generar código para que dichas conversiones sean también aplicables sobre el gestor de bases de datos destino de forma transparente.

El gestor de bases de datos Informix soporta conversiones implícitas de datos dentro de las expresiones SQL en las siguientes situaciones:

Comparaciones. Una conversión de datos ocurre cuando se comparan dos valores de diferente tipo.

Inserciones. Se produce una conversión de dato cuando se trata de insertar una valor de un tipo de variable en una columna de la base de datos de diferente tipo.

Operaciones aritméticas. Cuando se aplica un operador sobre valores de diferente tipo.

El gestor de bases de datos automáticamente invoca un casting implícito cuando necesita evaluar y comparar expresiones. Operaciones que requieran más que un casting implícito producen un error.

En la guía de referencia de SQL de Informix se contemplan los siguientes tipos de conversiones:

Número a número. Una conversión implícita se aplicará siempre y cuando esta sea posible, ósea, si el tipo de dato destino pueda albergar el valor de origen. En caso contrario se producirá un error.

En el caso tratarse de operaciones aritméticas Informix-SQL hace las mismas sobre valores de tipo DECIMAL independientemente de los tipos de datos de los operándoos.

Entre número y carácter y viceversa. La conversión entre valores tipo char a número será posible siempre y cuando la cadena contenga únicamente un valor numérico valido. El caso contrario siempre será posible si la longitud de la cadena puede albergar los dígitos del número a convertir.

Entre fecha y fecha-hora. Se pueden convertir valores tipo DATE a DATETIME siempre y cuando la precisión del tipo de datos destino tenga al menos hasta el día, si tiene más se completa, al hacer la conversión, con ceros.

Es posible expresar fechas mediante literales tipo cadena. Estas son convertidas automáticamente en valores tipo DATE o DATETIME siempre y cuando la cadena contenga un valor tipo fecha expresado en un formato adecuado: DATE = �mm/dd/yyyy� y DATETIME = �yy-mm-dd hh:mm:ss.fff�

En la tabla que se muestra a continuación se ilustran las conversiones implícitas soportadas por Informix. Las casillas sombreadas hacen referencia a conversiones no posibles y las otras a conversiones factibles aunque tiendo en cuenta las siguientes consideraciones:

Page 176: IfxToJava2

176

En algún caso puede haber posibles fallos de conversión o discrepancia entre los valores recibidos y los esperados.

Se pueden producir resultados inesperados bien por su valor o por su formato.

Tipo de dato destino Tipo de dato origen C

HA

R

VA

RC

HA

R

INTE

GE

R

SM

ALLIN

T

FLO

AT

SM

ALLFLO

AT

DEC

IMA

L

MO

NEY

DA

TE

DA

TE

TIM

E

INTE

RV

AL

CHAR Y Y Y Y Y Y Y Y Y Y

VARCHAR Y Y Y Y Y Y Y Y Y Y

INTEGER Y Y Y Y Y Y Y

SMALLINT Y Y Y Y Y Y Y Y

FLOAT Y Y Y Y Y Y Y SMALLFLOAT Y Y Y Y Y Y Y Y

DECIMAL Y Y Y Y Y Y Y Y

MONEY Y Y Y Y Y Y Y Y

DATE Y Y Y Y Y Y Y Y Y

DATETIME Y Y Y

INTERVAL Y Y

Tabla 34: Conversiones implícitas soportadas por Informix

No es soportada por Informix ninguna otra conversión que involucre tipos de datos binarios largos: TEXT y BYTE.

El resto de gestores de bases de datos tienen un comportamiento similar ante las conversiones implícitas. Todos ellos soportan este tipo de conversiones aunque cada uno con sus peculiaridades y restricciones.

A continuación se mostrarán las tablas de conversiones implícitas proporcionadas por cada proveedor de bases de datos y en el siguiente punto: tratamiento de las conversiones no implicitas se analizarán y buscarán soluciones para aquellas que puedan ser problemáticas a la hora de traducir código fuente Informix-SQL a código objeto ejecutable sobre al gestor de bases de datos destino.

Las tablas que se muestran a continuación siguen la misma nomenclatura que la vista al definir las conversiones implícitas soportadas por Informix.

En el caso de SqlServer si admite las conversiones implícitas y explícitas, estas ultimas con las funciones CAST Y CONVERT. En la tabla siguiente se muestras las conversiones implícitas admitidas por SqlServer:

Tipo de dato destino Tipo de dato origen B

INA

RY

VA

RB

INA

RY

CH

AR

VA

RC

HA

R

NC

HA

R

NV

AR

CH

AR

DA

TE

TIM

E

SM

ALLD

AT

ET

IME

DE

CIM

AL

NU

ME

RIC

FLO

AT

RE

AL

BIG

INT

INT

SM

ALLIN

T

TIN

YIN

T

MO

NE

Y

SM

ALLM

ON

EY

BIT

TIM

ES

TA

MP

UN

IQU

EID

EN

TIF

IER

IMA

GE

NT

EX

T

TE

XT

SQ

L_

VA

RIA

NT

BINARY Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

VARBINARY Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

Page 177: IfxToJava2

177

CHAR Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

VARCHAR Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

NCHAR Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

NVARCHAR Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

DATETIME Y Y Y Y Y Y

SMALLDATETIME Y Y Y Y Y Y

DECIMAL Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

NUMERIC Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

FLOAT Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y REAL Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

BIGINT Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

INT Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

SMALLINT Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

TINYINT Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

MONEY Y Y Y Y Y Y Y Y Y Y Y Y Y Y

SMALLMONEY Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

BIT Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y TIMESTAMP Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

UNIQUEIDENTIFIER Y Y Y Y Y Y Y

IMAGE Y Y Y

NTEST Y Y Y

TEXT Y Y Y

SQL_VARIANT

Tabla 35: Conversiones soportadas por SqlServer

En el caso del gestor de bases de datos Oracle, al igual que la mayoría de gestores, recomienda no usar conversiones implícitas y en su lugar las explícitas, por varias razones:

Pueden tener un impacto negativo en el rendimiento del gestor de bases de datos.

Dependiendo del contexto en el que se aplican se pueden comportar de diferente manera.

Los algoritmos para conversiones implícitas están sujetos a cambios según van saliendo nuevas versiones de software.

En la tabla que se muestra a continuación se plasma la matriz de conversiones implícitas que soporta Oracle:

Tipo de dato destino Tipo de dato origen C

HA

R

VA

RC

HA

R

DA

TE

TIM

ES

TA

MP

LO

NG

NU

MB

ER

RO

W

RO

WID

CLO

B

BLO

B

NC

HA

R

NV

AR

CH

AR

2

NC

LO

B

BIN

AR

Y_

FLO

AT

N B

INA

RY

_D

OU

BLE

CHAR Y Y Y Y Y Y Y Y Y Y Y

VARCHAR Y Y Y Y Y Y Y Y Y Y Y Y

DATE Y Y Y Y

TIMESTAMP Y Y Y Y Y

LONG Y Y Y Y Y Y Y Y NUMBER Y Y Y Y Y Y

ROW Y Y Y Y Y Y

ROWID Y Y Y Y

CLOB Y Y Y Y Y Y

BLOB Y

NCHAR Y Y Y Y Y Y Y Y Y Y Y Y

Page 178: IfxToJava2

178

NVARCHAR2 Y Y Y Y Y Y Y Y Y Y Y Y

NCLOB Y Y Y Y Y Y

BINARY_FLOAT Y Y Y Y Y Y

BINARY_DOUBLE Y Y Y Y Y Y

Tabla 36: Conversiones implícitas soportadas por Oracle

Para el gestor de bases de datos DB2 también existe la posibilidad de aplicar conversiones implícitas y explícitas. El gestor de bases de datos puede convertir implícitamente tipos de datos durante las asignaciones en las que participa un tipo diferente.

La Tabla 37 muestra las conversiones implícitas permitidas entre tipos de datos internos.

Tipo de dato destino Tipo de dato origen S

MA

LLIN

T

INTE

GE

R

DEC

IMA

L

REA

L

DO

UB

LE

CH

AR

VA

RC

HA

R

CLO

B

GR

AP

HIC

VA

RG

RA

PH

IC

DB

CLO

B

BLO

B

DA

TE

TIM

E

TIM

ES

TA

MP

RO

WID

SMALLINT Y Y Y Y Y Y

INTEGER Y Y Y Y Y Y

DECIMAL Y Y Y Y Y Y

REAL Y Y Y Y Y Y

DOUBLE Y Y Y Y Y Y

CHAR Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y

VARCHAR Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y CLOB Y Y Y Y Y Y

GRAPHIC Y Y Y Y Y Y Y Y Y Y Y Y Y Y

VARGRAPHIC Y Y Y Y Y Y Y Y Y Y Y Y Y Y

DBCLOB Y Y Y Y Y Y

BLOB

DATE Y Y

TIME Y Y

TIMESTAMP Y Y Y Y

ROWID Y Y Y

Tabla 37: Conversiones implícitas soportadas por DB2

Cuando se asigna un tipo de dato GRAPHIC o CHARACTER a otro tipo de dato se puede producir un truncado del valor final.

TRATAMIENTO DE LAS CONVERSIONES NO IMPLICITAS

Es importante mencionar que todo gestor de bases de datos contempla las conversiones implícitas con cierta preocupación debido principalmente a que pueden producirse errores de: precisión, trucado, etc. durante las mismas.

En el proceso de analizar si las conversiones implícitas definidas por Informix-SQL son también soportadas por el resto de gestores de bases de datos hay que tener muy presente los mapeos entre tipos de datos Informix-SQL y el resto de gestores definidos en la Tabla 29: Mapeo entre tipos de datos Informix-SQL y el resto de gestores y utilizados para la traducción del código fuente, que se ejecuta sobre el gestor de bases de datos, a código objeto. Solo interesará saber que son soportadas aquellas conversiones que se pueden llegar a producir en el gestor de base de datos destino y sobre los tipos de datos que se vayan a aplicar. Por ejemplo sobre SqlServer no se va producir un intento de conversión de un tipo de dato BIT a ningún otro debido a que ningún tipo de dato Informix-SQL que se va a traducir al tipo de dato SqlServer BIT durante el proceso de paso de código fuente a objeto. Según esto las tablas de conversiones implícitas proporcionadas

Page 179: IfxToJava2

179

por los proveedores se reducirán bastante como se verá en las tablas que se muestran seguidamente.

De las tablas que se muestran a continuación se han eliminado las conversiones implícitas de:

Los tipos de datos que contempla el gestor destino y el origen no, tales como BINARY y VARBINARY en SqlServer, NCHAR y NVARCHAR en Oracle, etc.

Aquellos tipos de datos que aunque se contemplan en gestor origen y destino en el primero no se definen conversión implícita tales como: TEXT, BYTE, etc. desapareciendo así la necesidad de estudiar en SqlServer los tipos de datos: TEXT e IMAGE, en Oracle los tipos: LONGRAW y CLOB y en DB2 los tipos: BLOB y CLOB.

En las tablas que se muestran a continuación se identifican en rojo aquellas conversiones que Informix-SQL trata como implícitas y que sin embargo de aplicarse sobre otro gestor producirían errores al no ser consideradas por estos como tal.

Es todas las tablas asociado al tipo de dato CHAR, y no de forma independiente, aparece el tipo de dato que permite cadenas de caracteres de tamaño superior al CHAR: TEXT, LONG, VARCHAR según el gestor que se este estudiando: CHAR/TEXT, CHAR/LONG, CHAR/VARCHAR, esto se hace así para denotar que se ha de tener en cuenta que el tipo CHAR de Informix-SQL se puede convertir en dichos tipos de datos sobre el gestor destino y aunque sobre dichos tipos no se contemple ninguna conversión implícita habrá que considerar estos casos a la hora de traducir código fuente a objeto.

La solución más común que se utilizará para solventar los problemas que se plantean sobre los gestores de bases de datos destinos para soportar las conversiones implícitas que define Informix-SQL será aplicar, a la hora de generar código, conversiones explicitas.

SQLSERVER

A continuación se muestra la tabla definitiva de conversiones posibles a utilizar en SqlServer y el estudio detallado cómo enfrentarse a aquellos casos en los que SqlServer no considera conversiones implícitas y sin embargo Informix-SQL sí.

Tipo de dato destino Tipo de dato origen

CH

AR

/te

xt

VA

RC

HA

R

DA

TE

TIM

E

DE

CIM

AL

NU

ME

RIC

FLO

AT

RE

AL

INT

SM

ALLIN

T

CHAR/text Y Y/N Y/N Y/N Y/N Y/N Y/N Y/N

VARCHAR Y Y Y Y Y Y Y Y

DATETIME Y Y

DECIMAL Y Y Y Y Y Y Y Y

NUMERIC Y Y Y Y Y Y Y Y

FLOAT Y Y Y Y Y Y Y Y

REAL Y Y Y Y Y Y Y Y

INT Y Y Y Y Y Y Y Y

SMALLINT Y Y Y Y Y Y Y Y

Tabla 38: Conversiones implícitas necesarias para SqlServer

Sobre el gestor de bases de datos SqlServer se plantean problemas, principalmente, sobre el tipo de datos DATETIME. La solución consistirá en utilizar la función de SqlServer: CONVERT que permite, entre otras, realizar la conversión explicita de tipos de datos fecha/hora a número3.

3 Para más información dirigirse a los libros de pantalla de Microsoft SQL

Page 180: IfxToJava2

180

La conversión implícita que Informix-SQL hace del tipo de dato DATE a número se basa en proporcionar el número de días desde el 1 de enero de 1900 de tal forma que para la fecha 31/12/1899 nos devuelve 0, para 01/01/1900 1 y para el resto de fechas la cuenta de días. En el caso de SqlServer el comportamiento es similar, la función CONVERT retorna la cuenta de días desde el 1 de enero de 1900 aunque para el día 01/01/1900 nos retorna el valor 0 y para 31/12/1899 nos retorna el valor �1.

Ejemplos de la función CONVERT de SqlServer:

CONVERT(int, expr_datetime,formato)

CONVERT(int, getdate()) = 39149 = 09/03/2007

CONVERT(int, CONVERT(datetime,'12/31/1899')) = -1 = 31/12/1899

CONVERT(int, CONVERT(datetime,'01/01/1900')) = 0 = 01/01/1900

A continuación se muestra un ejemplo práctico de cómo aplicar esta solución al problema sobre el gestor de base de datos SqlServer:

Codigo fuente:

Select count(*) from tablaX where campo_fecha = 1

Esta sentencia devolverá el número de filas de la tablaX donde el campo fecha tenga un valor de: 01/01/1900.

El código objeto Sqlserver será:

Select count(*) from tablaX where CONVERT(int, campo_fecha) = 1

Esta sentencia devolverá el número de filas de la tablaX donde el campo fecha tenga un valor de: 02/01/1900.

Como se puede observar, después de haber solventado el problema de la conversión implícita, el resultado de ejecutar la sentencia para Informix-SQL y SqlServer no es el mismo. Esto nos da píe a plantear otro problema: aunque SqlServer permita la conversión implícita de valor numérico a DATETIME el resultado de una operación sobre Informix-SQL no será el mismo que el de aplicar la misma operación sobre SqlServer ya ambos gestores interpretan ese valor numérico como una fecha distinta. La forma de tratar esta diferencia semántica así como los lugares donde será necesario tenerla en cuenta se estudiará posteriormente en el punto: Tratamiento de las fechas.

En la tabla de concesiones implícitas necesarias se marca la concesión de CHAR/TEXT a DATETIME, DECIMAL, NUMERIC, etc. con Y/N, con esto se trata de indicar que la conversión implícita de CHAR estos tipos de datos si es soportada, pero la de TEXT no. Esto no ha de ser tratado de forma especial ya que la aparición del tipo de dato TEXT es por la necesidad de conversión de cadenas grandes de Informix-SQL a SqlServer y una cadena grande es muy poco probable que contenga un valor susceptible de ser convertido a los tipos de datos destino indicados en la tabla.

ORACLE

Tipo de dato destino Tipo de dato origen

CH

AR

/lo

ng

VA

RC

HA

R

DA

TE

TIM

ES

TA

MP

NU

MB

ER

CHAR /long Y Y/N Y Y/N

VARCHAR Y Y Y Y

DATE Y Y

TIMESTAMP Y Y

NUMBER Y Y

Tabla 39: Conversiones implícitas necesarias para Oracle

Page 181: IfxToJava2

181

Como se ve en la tabla de conversiones implícitas necesarias para Oracle se plantean problemas sobre los tipos de datos: DATE, DATETIME y NUMBER. El tratamiento adoptado es el mismo que para el gestor de bases de datos SqlServer aplicar conversiones explicitas donde las implícitas no se puedan utilizar.

Como paso previo para entender la solución adoptada para cada uno de los casos es preciso conocer algunas funciones de Oracle, estas son:

TO_CHAR convierte el valor que recibe como primer parámetro a un tipo de dato VARCHAR2. Tiene varias definiciones:

TO_CHAR (<fecha_o_columna>, [ <formato> [, <nsl_parametro>] ])

TO_CHAR (<número_o_columna>, [<formato> [, <nsl_parametro>] ])

TO_CHAR (<cadena_o_columna>)

TO_NUMBER convierte el un valor tipo carácter: CHAR, VARCHAR2, NCHAR, o NVARCHAR2 que contiene un valor numérico a un valor de tipo NUMBER. Opcionalmente permite especificar el formato.

TO_NUMBER (<cadena_o_columna>, [ <formato> [,<nsl_parametro>] ])

TO_DATE convierte un valor de tipo cadena: CHAR, VARCHAR2, NCHAR, o NVARCHAR2 a un valor de tipo DATE. Si se omite el formato se entiende que este es el que haya por defecto, si este es: J, indicando calendario Juliano y en este caso el primer parámetro ha de ser un entero.

TO_DATE (<cadena_o_columna>, [ <formato> [,<nsl_parametro>] ])

TO_DATE (<número_o_columna>, [ <formato> ])

TO_TIMESTAMP convierte el valor que recibe como primer parámetro de tipo cadena: CHAR, VARCHAR2, NCHAR, o NVARCHAR2 a un valor de tipo TIMESTAMP.

TO_TIMESTAMP (<cadena_o_columna>, [ <formato> [,<nsl_parametro>] ])

CAST convierte el valor que recibe como parámetro en otro.

CAST (<expresión> AS <tipo_de_dato> )

Esta función está limitada a ciertos tipos de datos.

Para información más detallada sobré estas funciones referirse al manual de referencia SQL de Oracle.

La solución aportada para tratar las conversiones que en código fuente, Informix-SQL, se consideran implícitas y al tratar de ejecutarlas sobre el gestor destino, Oracle, producirían errores es:

Convertir de DATE a TIMESTAMP. Existen dos funciones explícitas que permiten hacer está conversión: TO_TIMESTAMP y CAST, a continuación se ponen dos ejemplos:

TO_TIMESTAMP(campo_date,'YYYY-MM-DD HH:MI:SS')

TO_TIMESTAMP('1999-12-01 11:00:00','YYYY-MM-DD HH:MI:SS')

CAST(campo_date AS TIMESTAMP)

Para Convertir de tipo de dato DATE a NUMBER se utiliza la función TO_NUMBER en combinación con TO_CHAR. La primera recibe un tipo de dato cadena y lo pasa a número y la segunda permite convertir un tipo de dato DATE a CHAR. Ejemplo:

TO_NUMBER(TO_CHAR(SYSDATE,'J')) 2454169 (sysdate = 09/03/2007)

TO_NUMBER(TO_CHAR(TO_DATE('01/01/1900','DD/MM/YYYY'),'J')) 2415021

TO_NUMBER(TO_CHAR(TO_DATE('31/12/1899','DD/MM/YYYY'),'J')) 2415020

Page 182: IfxToJava2

182

Esta función devuelve el número de días desde el 1 de enero del 4712 antes de Cristo.

La conversión explicita del tipo de dato TIMESTAMP a DATE se realiza con la función TO_DATE en combinación con TO_CHAR o con la función CAST también junto con TO_CHAR. A continuación se muestran ejemplos:

TO_DATE('11-10-99 01:23:45', 'MM-DD-YY')

TO_DATE(TO_CHAR(datetimecol, 'DD/MM/YYYY HH24:MI:SS'),�DD/MM/YYYY�)

TO_DATE(TO_CHAR(�10/12/2005 14:15:00�, 'DD/MM/YYYY HH24:MI:SS'),�DD/MM/YYYY�)

CAST(datetimecol AS DATE)

CAST( TO_CHAR(�10/12/2005 14:15:00�, 'DD/MM/YYYY HH24:MI:SS') AS DATE)

La última conversión a tener en cuenta es de NUMBER a DATE para ello se utilizará la función TO_DATE en conjunción con TO_CHAR. A continuación se muestran ejemplos:

TO_DATE ( TO_CHAR ( valor_numerico, '99999999999') , 'J')

TO_DATE ( TO_CHAR ( 103465, '99999999999') , 'J')

En el caso de que el gestor destino sea Oracle hay que tratar como explicitas tanto la conversión de número a fecha como de fecha a número y en este caso también debemos fijarnos en que el valor numérico es interpretado de forma diferente a como lo hace Informix-SQL, la forma de solventar esta diferencia semántica se verá en el punto: Tratamiento de las fechas.

Al igual que con el gestor de bases de datos SqlServer el tipo de datos origen CHAR/LONG tiene problemas a la hora de convertir de forma implícita el tipo LONG a tipo DATE y NUMBER. La solución adoptada será la misma: no hacer nada ya que son conversiones que no se van a producir, eso sí se recomienda se revise el código generado para garantizar la integridad en la traducción.

DB2

Tipo de dato destino Tipo de dato origen S

MA

LLIN

T

INTE

GE

R

DEC

IMA

L

REA

L

DO

UB

LE

CH

AR

/V

AR

CH

AR

VA

RC

HA

R

DA

TE

TIM

ES

TA

MP

SMALLINT Y Y Y Y Y Y

INTEGER Y Y Y Y Y Y

DECIMAL Y Y Y Y Y Y

REAL Y Y Y Y Y Y

DOUBLE Y Y Y Y Y Y

CHAR/VARCHAR Y Y Y Y Y Y Y Y

VARCHAR Y Y Y Y Y Y Y Y

DATE Y Y

TIMESTAMP Y Y Y

Tabla 40: Conversiones implícitas necesarias para DB2

Como se muestra en la tabla anterior para DB2 se plantean problemas al tratar de convertir el tipo de dato DATE a número y TIMESTAMP y con los tipos de datos numéricos a DATE. El tratamiento adoptado, a la hora de hacer que el código fuente Informix-SQL se pueda ejecutar sobre el gestor de bases de datos DB2, es el mismo que para el resto de gestores: utilizar conversiones explicitas donde las implícitas producirían errores.

Page 183: IfxToJava2

183

Para convertir el tipo de dato DATE a TIMESTAMP se utilizará una combinación de funciones soportadas por DB2. estas son:

CHAR que retorna una cadena correspondiente al valor formado por el dato que recibe como primer parámetro, tipo fecha, tras aplicarle el formato indicado en el segundo parámetro.

TIMESTAMP_FORMAT que convierte a tipo TIMESTAMP el valor de tipo cadena que recibe como parámetro.

CONCAT que retorna la cadena resultante de concatenar las dos valores de tipo cadena que recibe como parámetros.

La combinación de estas funciones que nos permite hacer esta conversión explicita es:

TIMESTAMP_FORMAT(CONCAT(CHAR(campo_date,ISO),' 00:00:00'),'YYYY-MM-DD HH24:MI:SS')

TIMESTAMP_FORMAT(CONCAT('2007-03-09',' 00:00:00'),'YYYY-MM-DD HH24:MI:SS')

La conversión de NUMBER a DATE se puede conseguir utilizando la función DATE. Esta función recibe como parámetro una fecha en formato cadena o un número que representa el número de días menos 1 desde el 1 de enero de 0001.

DATE(número)

DATE(693595) 1899-12-31

La conversión de DATE a NUMBER se realiza con la función DAYS la cual retorna el número de días + 1 desde el 1 de enero del 0001 recibiendo como parámetro la fecha en formato cadena, fecha o fecha/hora.

DAYS(CHAR(campo_date,LOC))

DAYS(�03/09/2007�) 732744

DAYS(�01/01/1900�) 693596

DAYS(�31/12/1899�) 693595

DAYS(CHAR(campo_date,LOC))

Aparte de las conversiones explicitas necesarias se habrá de aplicar algún tipo de conversión cuando se trate de operar con algún valor numérico que represente una fecha ya que el mismo número no proporcionará la misma fecha en Informix-SQL y Db2. La forma de llevar a cabo esta transformación se explicará en el punto: Tratamiento de las fechas.

EXPRESIONES SQL Una expresión es una combinación de uno o mas valores, operadores, y/o funciones SQL que como resultado de su evaluación se obtiene un valor.

Es importante hacer mención especial a la definición que Informix-SQL hace de las expresiones SQL ya que, al igual que el resto de la Sintaxis de Informix-SQL, se ha de procurar que sea portable a cualquier otro de los gestores de bases de datos en estudio. Informix-SQL subdivide las expresiones SQL en:

Expresiones de manejo de columnas.

Expresiones de constantes.

Funciones SQL.

Expresiones agregadas.

Y Nombres de variables.

Page 184: IfxToJava2

184

Las expresiones SQL de Informix-SQL se utilizan: a la hora de seleccionar un elemento de una tabla en la sentencia SELECT, en la parte SET de la sentencia UPDATE, en la sentencia CHECK, en la parte HAVING de la sentencia SELECT y en cláusula WHERE de las sentencias SELECT, UPDATE y DELETE.

Como partimos de programas sintácticamente correctos no es el objetivo de esta sección el evaluar o garantizar que se utiliza adecuadamente una expresión SQL dentro de la definición de una sentencia sino que lo que se pretende es tener claros los elementos que definen una expresión SQL para así poder evaluar la compatibilidad y potabilidad del código fuente al resto de gestores de bases de datos.

La definición sintáctica es la siguiente:

<expresión> ::= [ + | - ] <tipos_de_expresion> <mas_tipos_de_expresion> <mas_tipos_de_expresion> ::= [ [ + | - | * | / ] <tipos_de_expresion> <mas_tipos_de_expresion> ] | vacio <tipos_de_expresion> ::= [ <expresion_columna> | <expresion_cte> | <expresion_funcion> | <expresion_agregada> | <variable> | ( <expresión> ) ]

EXPRESIONES DE MANEJO DE COLUMNAS

Simplemente definen la forma de acceder a una columna de una tabla, la sintaxis admitida por Informix-SQL es:

<expresion_columna> ::= [ { <nombretabla> | <aliastabla> | <nombresinonimo> | <nombrevista> } . ] <nombrecolumna> [ [ n , m ] ] | ROWID <nombretabla> | <aliastabla> | <nombresinonimo> | <nombrevista> ::= [ propietario . ] identificador

Esta sintaxis es básicamente admitida por el resto de gestores de bases de datos.

En Oracle si se especifica el propietario en la parte de la cláusula SELECT en la cual se seleccionan los campos también debe especificarse en el cláusula WHERE. Ejemplo:

Sentencia Informix: select usuario.tabla.campo1 from tabla1

Sentencia generada para Oracle: select usuario.tabla.campo1 from usuario.tabla1

Sentencia generada para el resto: select usuario.tabla.campo1 from tabla1

Esta peculiaridad de Oracle es considerada a la hora de traducir el código fuente a objeto.

Al indicar el nombre de columna Informix-SQL permite limitar el número de caracteres del campo que se retornan utilizando para ello la sintaxis opcional: [ n, m ] donde n y m son literales numéricos que representan: n indica la posición del carácter inicial y m la del final. El resto de gestores no soportan esta sintaxis, al menos con este mismo significado, pero todos ellos definen alguna función que permite obtener una subcadena de un campo, estas son:

Para SqlServer la función: SUBSTRING ( nombrecolumna, n�, m� ), donde n es el carácter inicial y m la longitud del substring.

Para Oracle la función: SUBSTR ( nombrecolumna, n�, m� ), donde n es el carácter inicial y m la longitud del substring.

Y para DB2 la función: SUBSTR ( nombrecolumna, n�, m� ), donde n es el carácter inicial y m la longitud del substring.

En Informix-SQL y también en el resto de gestores las cadenas de caracteres van desde 1 hasta la longitud de la misma.

Teniendo en cuenta que n y m son literales y que sabemos la forma de simular el mismo comportamiento en el resto de gestores no habrá ningún problema en traducir esta sintaxis al gestor de base de datos destino. Los valores de n� y m� se calculan:

Page 185: IfxToJava2

185

n�: es igual a n para cualquier gestor.

m�: para el resto de gestores se calcula aplicando la formula: m-n+1

Ejemplos:

Código fuente Informix-SQL: select campo1[2,4] from tabla

Código objeto Oracle: select substr(campo1,2, (4-2+1) ) from tabla

Código objeto SqlServer: select substring(campo1,2,3) from tabla

Código objeto DB2: select substr(campo1,2,3) from tabla

Donde m� se calculo aplicando la formula indicada: m-n+1 ósea: 4-2+1

Dentro del Anexo I, en la sección: Ejemplo de manejo de columnas y constantes predefinidas, se pueden ver ejemplos prácticos del uso de nombres de campos y substrings.

Otro elemento que aparece en la definición del manejo de columnas es el ROWID. El rowid es un número único y secuencial que Informix asigna a cada uno de los registros (filas) insertados en una tabla. Se podría decir que es un "índice único interno de Informix". Este número es único para una fila dentro de una tabla, lo cual no implica que otra fila de otra tabla pueda tener el mismo.

Ejemplo: SELECT MAX(rowid) FROM tabla

El concepto de ROWID no es soportado por todos los gestores. Oracle e Informix lo implementan, aunque Informix lo interpreta como un valor entero y Oracle como uno tipo cadena de longitud de 18 caracteres, esto de por si ya es un problema a la hora de traducir código fuente a objeto, veamos los siguientes ejemplos:

Ejemplo1: delete from tabla where rowid == (select max(rowid) from tabla )

Ejemplo2: select max(rowid) into vble1 from tabla; delete from tabla where rowid = vble1

El primer ejemplo es valido tanto para Oracle como para Informix-SQL, pero el segundo se apoya en una variable intermedia definida en el código fuente de Informix, de tipo integer, con lo cual este código al ser ejecutado sobre el gestor de base de datos Oracle dará un error. Haciendo un análisis mas profundo quizá pudiese solventarse este problema basándonos en la posibilidad que da Java de definir variables de forma bastante libre.

Ejemplo de consulta del ROWID sobre Informix:

select rowid,* from tabla;

rowid campo1 257 25/07/2006 258 25/07/2006 259 25/07/2006 260 25/07/2006 261 25/07/2006 262 25/07/2006 263 31/12/1900 264 25/07/2006

Ejemplo de consulta del ROWID sobre Oracle:

SQL> select rowid, tabla.* from tabla

ROWID UNO DOS

------------------ ------ ---------

AAADJiAABAAADhNAAA 1 1 AAADJiAABAAADhNAAB 2 1 AAADJiAABAAADhNAAC 3 1 AAADJiAABAAADhNAAD 4 1 AAADJiAABAAADhNAAE 5 1 AAADJiAABAAADhNAAF 6 1 AAADJiAABAAADhNAAG 7 1

Page 186: IfxToJava2

186

Por otra lado Db2 y SqlServer no soportan el concepto de ROWID, ambos gestores entienden que los programadores que deseen trabajar con el número único de fila deben definirlo explícitamente en la declaración de la tabla, añadiendo para ello un campo adicional. Lo que si proporcionan son los elementos para que el programador pueda implementar esta funcionalidad.

Para el caso de SqlServer se definen el tipo de dato UNIQUEIDENTIFIER, la opción ROWGUIDCOL, y la función NEWID() que proporciona el identificador único. La opción ROWGUIDCOL permite luego que en la sentencia SELECT se pueda retornar el ROWID sin especificar ningún campo de la tabla, véase el siguiente ejemplo:

create table tabla1 (

campo1 uniqueidentifier ROWGUIDCOL,

campo2 smallint

);

insert into tabla1 values (newid(),1);

select ROWGUIDCOL,* from tabla1

Resultados:

campo1 campo1 campo2 F1AC0A33-BBB6-4C47-8E40-179DD83C8EAA F1AC0A33-BBB6-4C47-8E40-179DD83C8EAA 1 A8908CB3-7230-43C4-BE39-0E0194D3380E A8908CB3-7230-43C4-BE39-0E0194D3380E 1 38679D43-0EF3-40BD-A132-D651BF98F909 38679D43-0EF3-40BD-A132-D651BF98F909 1 B7334E8B-5D61-429B-B339-F7E2A22440C1 B7334E8B-5D61-429B-B339-F7E2A22440C1 1 095BA7DA-5A43-4B00-8BA5-F513221E1624 095BA7DA-5A43-4B00-8BA5-F513221E1624 1 CBCF8013-274A-4593-ADD7-AA0C0CBFE4FA CBCF8013-274A-4593-ADD7-AA0C0CBFE4FA 1 4DDA3709-380E-4B90-BBB1-1648414E9A5A 4DDA3709-380E-4B90-BBB1-1648414E9A5A 1

El ROWGUIDCOL es un número único de forma global: este número no lo contendrá ninguna otra fila de ninguna otra tabla de ninguna base de datos. Aunque este concepto es mucho más global que el definido en Informix-SQL tiene el mismo significado que el ROWID. Para traducir el concepto ROWID de Informix-SQL a SqlServer se nos plantean dos problemas difíciles de solventar:

El primero, al igual que Oracle, el tipo de dato que retorna que es una cadena de 32 caracteres.

Y el segundo y más insalvable nos obliga a cambiar la estructura de las tablas originales añadiéndoles un campo nuevo el cual hay que tratar en el resto del código (insert, delete, etc.)

Otra forma que se puede plantear es mediante la siguiente definición:

create table tabla1 (

campo1 uniqueidentifier ROWGUIDCOL default newid(),

campo2 smallint

);

De esta forma no es preciso insertar los valores directamente aunque cambia la sintaxis de la sentencia insert:

insert into tabla1 (campo2) values (1);

select ROWGUIDCOL,* from tabla1

Resultados:

campo1 campo1 campo2 F1AC0A33-BBB6-4C47-8E40-179DD83C8EAA F1AC0A33-BBB6-4C47-8E40-179DD83C8EAA 1 A8908CB3-7230-43C4-BE39-0E0194D3380E A8908CB3-7230-43C4-BE39-0E0194D3380E 1 38679D43-0EF3-40BD-A132-D651BF98F909 38679D43-0EF3-40BD-A132-D651BF98F909 1

Page 187: IfxToJava2

187

B7334E8B-5D61-429B-B339-F7E2A22440C1 B7334E8B-5D61-429B-B339-F7E2A22440C1 1 095BA7DA-5A43-4B00-8BA5-F513221E1624 095BA7DA-5A43-4B00-8BA5-F513221E1624 1 CBCF8013-274A-4593-ADD7-AA0C0CBFE4FA CBCF8013-274A-4593-ADD7-AA0C0CBFE4FA 1 4DDA3709-380E-4B90-BBB1-1648414E9A5A 4DDA3709-380E-4B90-BBB1-1648414E9A5A 1

SQLSERVER sugiere otras formas de devolver un valor único para cada fila de la tabla que aunque no cumple el concepto de ROWGUIDCOL si cumpliría la definición que Informix-SQL hace del ROWID. Estas soluciones se basan en añadir código en los programas basado en las funciones propias de SQLSERVER: rank(), count(), y row_number()4.

En el caso de que el gestor de base de datos destino sea DB2 la implementación del ROWID es muy similar a la de SqlServer con la diferencia que el campo de tipo ROWID, según se defina, permite que el valor se genere de forma automática y por otro lado no admite la consulta del mismo utilizando una palabra reservada, véase el siguiente ejemplo:

Create table tabla1 (

camporowid ROWID NOT NULL GENERATED ALWAYS,

campo2 smallint

);

db2 => select * from tabla1

camporowid campo2

------ -------------------- �!AYCQs 1 �!B�y3� 1 �!B�H4� 1 �!B��&8 1 �!B��V� 1 �!B�5C$ 1

Esta definición guarda el identificador único en una variable de 17 bytes. La opción �GENERATED ALWAYS� indica que no se deben insertar los valores de forma explicita sino que el gestor se encarga de ello.

Esta definición permite generar el concepto de rowid como lo entiende Informix-SQL: un único valor por cada columna de la tabla lo cual permite identificarlas de forma univoca. Los valores que almacena una variable de tipo ROWID son de tipo caracteres de longitud variable a diferencia de Informix que son valores numéricos.

Una forma de definir un campo numérico que simule el comportamiento del ROWID es la siguiente:

Create table tabla1 (

camporowid integer NOT NULL GENERATED ALWAYS AS IDENTITY,

campo2 smallint

);

El atributo �AS IDENTITY� junto con �GENERATED ALWAYS� genera automáticamente valores numéricos incrementales (o decrementales) cuando una nueva columna es insertada en la tabla.

db2 => select * from tabla1

4 Ejemplos en los enlaces: http://www.databasejournal.com/features/mssql/article.php/3572301 y http://support.microsoft.com/default.aspx?scid=KB;EN-US;q186133

Page 188: IfxToJava2

188

camporowid campo2

------ -------------------- 1 1 2 1 3 1 4 1 5 1 6 1

Un problema adicional de DB2 es que no proporciona ningún método para recuperar el valor de tipo rowid, la única forma de recuperarlo es accediendo al nombre del campo, no permite usar palabras reservadas tales como: ROWID o ROWGUIDCOL. Otro problema que se plantea es que Db2 obliga a cambiar las sentencias insert indicando en todo caso los campos sobre los que trabajan, las siguientes instrucciones provoca un error:

db2 => insert into tabla1 values(1,1)

db2 => insert into tabla1 values(1)

La forma de realizar la inserción sería:

db2 => insert into tabla1 (campo2) values(1)

Según el estudio realizado el ser capaces de pasar el concepto del rowid al resto de gestores podría forzar a redefinir el código fuente e incluso plantear el cambiar estructuras de alguna tabla lo cual excede el estudio aquí planteado. Aún así se proporcionan múltiples ideas que pueden ser útiles a al hora de tratar el rowid y que en futuras versiones incluso se planteará el tenerlas en cuenta a la hora de generar código objeto para cada diferente gestor.

Si en el código fuente aparece esa palabra reservada se notificará por pantalla, en el momento de la traducción, para que se proceda a revisar el código objeto generado.

EXPRESIONES DE CONSTANTES

Informix-SQL Admite como expresiones constantes las siguientes:

Cadenas entre comillas (simples y dobles), literales numéricos, literales de definición de fechas y de definición de intervalos.

Constantes USER, TODAY y CURRENT.

La definición de constantes esta íntimamente relacionado con los tipos de datos soportados por el gestor de bases de datos. Destacar que Informix-SQL permite definir constates tipo cadena entre comilla doble y entre comilla simple y como el resto de gestores trabajan con la comilla simple (ver estudio realizado en el apartado: Configuración local ) en la traducción de código se usará siempre comilla simple. A continuación se muestra la definición sintáctica:

<cadena_caractares> ::= � [ caracter | �� ] � | � [ caracter | � ] �

La definición sintáctica de la constante numérica se muestra a continuación:

<número> ::= [ + | - ] { digito [..n] [.] [digito] | [.] digito[..n] } [ E [-] digito[..n] ]

Esta definición es soportada por todos los gestores de bases de datos.

En Informix-SQL para definir una constante tipo DATE se puede hacer de varias formas: con un número entero que indica el número de días desde el 31/12/1899 o bien con una cadena de caracteres en el formato mm/dd/yyyy (según configuración local).

Las constantes tipo DATE en formato cadena de caracteres se pueden pasar directamente al gestor de bases de datos, siempre y cuando la configuración local sea igual en todos los gestores (ver apartado: Configuración local), con el único cambio de sustituir la comilla doble por comilla simple.

Aunque todos los gestores reconocen la constante fecha en formato cadena se pueden producir errores al realizar operaciones con esta, como en el caso de sumar una constate numérica a una fecha o restar dos fechas o pasárselo como parámetro a funciones que esperan recibir un tipo dato

Page 189: IfxToJava2

189

DATE, por lo que para evitar problemas en la ejecución y/o hacer que el código sea más correcto, aunque en casos algo menos legible, se pasará la constante de caracteres a un tipo de dato: DATE utilizando para ello las funciones propias de cada gestor de bases de datos.

La siguiente sentencia ejecutada sobre el gestor de bases de datos Oracle produciría un error, ya que éste entiende que se está intentado hacer una operación aritmética sobre una cadena y un entero, mientras que Informix lo admite sin problemas:

select �31/12/2007� + 1 from tabla

Cuando aparezca, en el código fuente, una constante cadena con formato fecha se aplicará, en función del gestor destino, la siguiente traducción:

Oracle: to_date(�fecha_cad�,'formato_fecha'), caso práctico:

to_date(�31/12/2007�,�dd/mm/yyyy�);

Sqlserver: convert(datetime,�fecha_cad�,formato_fecha), caso práctico:

convert(datetime,�31/12/2007�,103);

Db2: date(fecha_cad), caso práctico:

date(�31/12/2007�);

A la hora de hacer la traducción de código el formato_fecha se generará en función de la configuración local establecida en el fichero de configuración de la conexión ver: Este fichero se llama: conexion.cfg, y Al igual que ocurre con las constantes tipo DATE en formato cadena las constantes tipo DATE en formato numérico, aunque en la mayoría de los casos son soportadas por el gestor destino, es recomendable utilizar las funciones propias de cada gestor para pasarlas a tipo fecha, estas son:

Oracle: to_date( to_char (fecha_num,'formato_fecha'), formato ), caso práctico:

to_date( to_char( 1,�99999999999�),�J�);

Sqlserver: convert(datetime, fecha_num,formato_fecha), caso práctico:

convert(datetime, 1 ,103);

Db2: date(fecha_num), caso práctico:

date(1);

Como se comentó en el punto en el que se estudiaban las conversiones implícitas soportadas por cada gestor un mismo valor numérico no será interpretado como la misma fecha en todos los gestores. La forma de llevar a cabo, en la práctica, esta transformación de número a fecha se estudia en el punto: Tratamiento de las fechas.

Para definir una constante de tipo DATETIME Informix-SQL tiene una sintaxis mucho más específica, la cual se muestra a continuación:

<literal_datetime> ::= DATETIME ( <numeric_datetime> ) <datetime_calificador> <numeric_datetime> ::= yyyy-mm-dd hh:mm:ss.ffffff <datetime_calificador> ::= { year | month | day | hour | minute | second | fraction } to { year | month | day | hour | minute | second | fraction [ (3) | ( número ) ] }

También admite directamente el formato de cadena con un DATETIME embebido: 'yyyy-mm-dd hh:mm:ss.ffffff'.

Las constantes tipo fecha/hora en el formato propio de Informix-SQL no es soportado por ningún otro gestor de bases de datos con lo que será preciso realizar un procesamiento de este tipo de constantes para pasarlas a un formato que entienda el gestor de bases de datos destino. Por otro lado las constantes tipo fecha/hora en formato cadena si son soportadas por el resto de gestores

Page 190: IfxToJava2

190

sin apenas limitaciones, a continuación se muestran las conversiones a realizar para cada uno de los gestores de bases de datos estudiados:

Para el gestor de bases de datos Oracle ha de recibir las constantes tipo fecha/hora como una cadena de caracteres y justo antes de ella la palabra reservada timestamp. Así los dos casos que se pueden dar en Informix-SQL se deben convertir a este formato:

timestamp �yyyy-mm-dd hh:mm:ss.fff�

Ejemplos:

�2006-08-25 22:10:12.453� timestamp �2006-08-25 22:10:12.453�

datetime (2006-08-25 22:10:12.453) year to fraction

timestamp �2006-08-25 22:10:12.453�

SQLSERVER solo reconoce como validos los datos fecha/hora incluidos entre comilla simple con los siguientes formatos:

Formatos alfabéticos de fecha (por ejemplo, '15 de abril de 1998')

Formatos numéricos de fecha (por ejemplo, '15/4/1998', '15 de abril de 1998')

Formatos de cadenas sin separar (por ejemplo, '19981207', '12 de Diciembre de 1998')

Dadas que estas son las únicas posibilidades de definir constantes tipo fecha la forma de solventar el problema consiste en utilizar la función CONVERT, para ello se ha de extraer del código fuente la constate tipo cadena con una fecha/hora embebida o el literal datetime y generar código objeto siguiendo la siguiente sintaxis:

convert(datetime,cadena,formato_fecha_hora)

Ejemplos:

�2006-08-25 22:10:12.453� convert(datetime,�2006-08-25 22:10:12.453�,121)

datetime ( 2006-08-25 22:10:12.453 ) year to fraction

convert(datetime,�2006-08-25 22:10:12.453�,121)

Donde 121 es el código que utiliza SqlServer para indicar formato fecha/hora.

Db2. No plantea ningún problema al admiten sin restricciones las definiciones de constantes y literal fecha/hora que hace Informix-SQL.

Tanto el reconocimiento de los tipos de dato fecha como fecha/hora que están introducidos como constantes de tipo cadena se realiza dentro del analizador léxico punto el cual seremos capaces de discernir si se trata de un token tipo fecha, fecha/hora o por el contrario cadena, ver: Reconocimiento de las fechas.

La identificación y utilización de las constantes tipo fecha y fecha-hora dentro de expresiones SQL se estudiarán con detalle con posterioridad en el apartado: Tratamiento de las fechas.

Para ver ejemplos del comportamiento del traductor en el tratamiento de literales, constates y variables dirigirse a: Ejemplo de manejo de literales, constantes y variables dentro del Anexo I.

La función TODAY retorna la fecha del sistema como un tipo de datos DATE. Esta función como tal no existe en el resto de gestores, pero existen otras similares que teniendo en cuenta la Tabla 29: Mapeo entre tipos de datos Informix-SQL y el resto de gestores, son correctas para ser utilizadas en el gestor de bases de datos destino:

En SqlServer la función GETDATE(), retorna la fecha actual en formato fecha y hora.

En Oracle la constante SYSDATE que retorna la fecha y hora actual. No recibe parámetros.

En DB2 la constante CURRENTE DATE retorna la fecha actual del sistema.

Page 191: IfxToJava2

191

Tener en cuenta que GETDATE() y SYSDATE retornan un valor DATETIME y las variables sobre el cual se almacena, en la base de datos, guardan la parte de hora. Esto puede afectar al resultado de las operaciones realizadas con los valores devueltos por estas funciones proporcionando datos diferentes a los que se producirían si se ejecutase sobre el gestor de bases de datos original. A la hora de traducir esta constante para Sqlserver y Oracle se utilizarán, respectivamente, las expresiones:

En SqlServer: DATEPART(dd,0, DATEDIFF(dd,0,GETDATE()))

Para Oracle: TO_DATE(TO_CHAR(SYSDATE,'dd/mm/yyyy'))

En los casos prácticos relativos a operaciones aritméticas sobre fechas, punto: ¡Error! No se encuentra el origen de la referencia., se detalla el problema y solución con ejemplos.

La constante CURRENT de Informix-SQL es similar a TODAY, pero en este caso retorna un tipo de dato DATETIME que contiene la fecha y hora mostrando el momento en el tiempo actual. Según su definición las funciones equivalentes en el resto de gestores son:

En SqlServer la función GETDATE(), retorna la fecha actual en formato fecha y hora.

En Oracle la constante SYSDATE que retorna la fecha y hora actual.

En Db2 la constante CURRENTE TIMESTAMP retorna la fecha y hora actual del sistema.

USER es una función, sin parámetros, que retorna un cadena de caracteres que contiene el login del usuario actual (esto es, la persona que esta ejecutando el proceso). SqlServer define la constante USER como el usuario actual de base de datos lo cual viene a ser lo mismo que Informix ya que este no trabaja con usuarios de base de datos sino con usuarios del sistema. Oracle también define esta constante como el usuario que ha iniciado la sesión actual. Y Db2 también define esta constante con similar significado, con lo que se podrá usar esta función sin ningún problema contra cualquier gestor de bases de datos.

Los ejemplos del comportamiento del traductor con las constantes: TODAY, CURRENT y USER se muestra en punto: Ejemplo de manejo de columnas y constantes predefinidas dentro del Anexo I.

FUNCIONES SQL

El gestor de bases de datos Informix define una serie de funciones que pueden ser utilizadas dentro de una expresión SQL y por tanto procesadas por el mismo. Estas funciones son: DAY, MONTH, WEEKDAY, YEAR, DATE, EXTEND, MDY, LENGHT, HEX, TRUNC Y ROUND. A continuación se estudia cada una de ellas y la compatibilidad con el resto de gestores de bases de datos.

DAY ( [ date_expr | datetime_expr ] ) Esta función retorna un número entero que representa el día del mes del valor tipo DATE o DATETIME que recibe como parámetro.

Esta función es soportada por SqlServer y Db2 con idéntica sintaxis y semántica que Informix-SQL. Oracle no la define aunque si se puede obtener el mismo resultado utilizado la función TO_CHAR, como se muestra en el siguiente ejemplo:

TO_CHAR(campo_tipo_fecha,'DD')

TO_CHAR(sysdate,'DD')

MONTH ( [ date expr | datetime expr ] ) Esta función retorna un número entero de 1 a 12 que representa el mes del valor tipo DATE o DATETIME que recibe como parámetro.

Esta función es soportada por SqlServer y Db2 con la misma sintaxis y semántica que Informix-SQL. Para obtener el día del mes en oracle se puede utilizar la función TO_CHAR como se muestra en a continuación:

TO_CHAR(campo_tipo_fecha,'MM')

WEEKDAY ( [ date expr | datetime expr ] ) Esta función retorna un entero que representa el día de la semana. Para Informix-SQL: cero representa domingo, 1 lunes y así sucesivamente.

Para obtener el día de la semana en el resto de gestores de bases de datos se ha de utilizar:

Page 192: IfxToJava2

192

En SqlServer no existe una función exclusiva que nos de el día de la semana. Se debe de usar la función DATEPART(gw, campo_date). Esta función retorna domingo = 1 y sábado = 7. La operación a realizar durante el proceso de traducción de código fuente a objeto será:

WEEKDAY (today) DATEPART(dw, getdate())

En Oracle la forma de obtener el día de la semana se ha de aplicar la siguiente consulta: TO_CHAR(sysdate,'D') la cual retorna un número del 1 al 7 tomando el 1 como lunes y el 7 como domingo. Al igual que con SqlServer la traducción a realizar del código fuente será:

WEEKDAY (today) TO_CHAR(sysdate,�D�)

En Db2 existe la función DAYOFWEEK ( campo_date ) que retorna un número del 1 al 7 donde 1 representa domingo. Al igual que para el resto de gestores la forma de traducir la expresión de Informix-SQL será:

WEEKDAY (today) DAYOFWEEK (current date)

La representación del día de la semana como número al igual que el formato de fecha y otros parámetros dependerá de como este configurado el gestor de bases de datos: idioma, fecha, etc. A la hora de realizar la traducción de estas funciones al gestor de bases de datos destino habrá que tener en cuenta como interpreta este el día de la semana y hacer la corrección, si es necesaria, para que el comportamiento sea igual al que se diseñó en el código fuente para el gestor de bases de datos Informix. Ver el apartado: Configuración local para más detalles.

YEAR ( [ date expr | datetime expr ] ) Retorna 4 dígitos que representan el número de año del valor DATE o DATETIME que recibe como parámetro.

Esta función es soportada por SqlServer y Db2 con la misma sintaxis y semántica que Informix-SQL. Para obtener el año en Oracle hay que utilizar la función TO_CHAR como se muestra a continuación:

TO_CHAR(campo_tipo_fecha,'YYYY')

TO_CHAR(sysdate,'YYYY')

DATE ( nondate_expr ) Esta función retorna un valor tipo DATE correspondiente a la expresión de tipo no DATE que recibe como parámetro. El tipo de parámetro que suele recibir son CHAR, INTENTER o DATETIME. Cuando recibe un parámetro tipo CHAR la función DATE lo evalúa teniendo en cuenta la variable de entorno DBDATE. Si se recibe un tipo de dato INTEGER entiende que es el número de días que van desde el 31/12/1899. Y si recibe un valor de tipo DATETIME retorna la parte fecha del mismo.

Para que el resultado de la misma sea igual que el que produciría si se ejecutase sobre el gestor de bases de datos Informix es importante saber el formato de fechas que admite esta función el cual dependerá del formato de fechas que tenga el gestor destino.

La traducción de esta función para el resto de gestores de bases de datos ha de considerar los tres tipos de datos que puede recibir como parámetro. A continuación se indica se trataría la función DATE por cada gestor:

Db2. Define la función DATE como Informix y admite como parámetros: entero, timestamp, cadena de 7 caracteres o representando una fecha valida. Si el valor es un timestamp retorna la parte fecha. Si es una fecha en formato caracter la interpreta. El parámetro de entrada cadena de 7 caracteres no se producirá. Y si recibe un número la fecha se obtiene sumando n-1 días al 1 de enero de 0001. Ej.:

DATE(expr_date_time) ó DATE(expr_caracter) ó DATE(expr_número)

En Oracle se utiliza la función: TO_DATE en combinación, en algún caso, con otras como: TO_NUMBER o TO_CHAR. Véanse los siguientes los casos posibles:

TO_DATE(TO_CHAR(expr_date_time, 'DD/MM/YYYY HH24:MI:SS'),�DD/MM/YYYY�)

TO_DATE(TO_CHAR(expr_numerica,�999999999999�), �J�)

TO_DATE(expr_caracter, 'DD/MM/YYYY�)

Page 193: IfxToJava2

193

El gestor de base de datos SqlServer no define la función DATE pero si una que permite obtener el mismo resultado. La función a utilizar es CONVERT. A continuación se muestras los casos que se pueden plantear:

CONVERT(datetime, expr_date_time, formato) Esta no tiene sentido ya que Sqlserver no tiene un tipo de datos DATE y otro DATETIME sino que solo utiliza el tipo de datos DATETIME.

CONVERT(datetime, expr_caracter)

CONVERT(datetime, expr_numerica, formato)

El único caso que plantea problemas aquí es el parámetro numérico de entrada ya que el mismo número proporcionará una fecha diferente en función de sobre que gestor de bases de datos se lance la función. La solución a este problema se muestra en el apartado: Tratamiento de las fechas.

EXTEND ( [ date_expr | datetime_expr ] [, Datetime qualifier ] ) Esta función ajusta la precisión de un valor del tipo de dato DATE o DATETIME. Si no se indica la precisión se entiende que va desde año hasta fracción de segundo con 3 dígitos de precisión. La expresión no puede ser una constante tipo cadena. Si se pretende ajustar el nuevo tipo de datos a uno con mayor precisión de la que tiene la expresión original los campos de mes y día toman, por defecto, el valor de 1 y los de hora, minutos, segundos, y fracción de 0.

En el fondo esta función lo que realiza es un cambio de formato de del tipo de dato fecha/hora que recibe como parámetro. Para poder traducirla al resto gestores habrá que convertir el segundo parámetro al formato que reconoce cada gestor, que suele ser: �dd-MM-yyyy hh:mm:ss.fff�, y tener en cuenta también el formato de fecha que este establecido en la configuración del cliente y su posible.

Uno cualificador valido par Informix tiene la sintaxis:

<DATETIME_QUALIFIER> ::=

{ YEAR | MONTH | DAY | HOUR | MINUTE | SECOND | FRACTION } TO { YEAR | MONTH | DAY | HOUR | MINUTE | SECOND | FRACTION [ ( n ) ]}

Las funciones a utilizar son:

Para Oracle:

TO_DATE(TO_CHAR(expr_date_time, 'DD/MM/YYYY HH24:MI:SS.FFFFFF'), formato)

Como la función TO_DATE recibe como primer parámetro una cadena de caracteres que representa un tipo de datos fecha/hora y la función original de informix recibe un tipo de dato fecha/hora se convertirá este a cadena con el patrón: 'DD/MM/YYYY HH24:MI:SS.FFFFFF' con el objeto de no perder precisión. El segundo parámetro de esta función se construirá en tiempo de ejecución adaptando el formato de Informix-SQL a uno que admita Oracle, para ello se utilizará la tabla de �elementos de formato Datetime� definida por Oracle en su manual de referencia SQL y la configuración local (ver punto: Configuración local).

En lugar de la función TO_DATE se puede utilizar la función TO_DATETIME que recibe como primer parámetro una valor fecha/hora en formato cadena y como segundo una cadena indicando el formato y retorna un valor tipo fecha/hora. Ej.:

TO_TIMESTAMP ('1999-12-01 11:00:00', 'YYYY-MM-DD HH:MI:SS')

Para SqlServer: CONVERT(datetime, expr_date_time, formato)

El formato se de elegir, al igual que para Oracle, teniendo en cuenta la configuración local y la tabla de formatos definida por SqlServer en los: �Libros de pantalla de Microsoft SqlServer� asociados a la función CONVERT.

Para DB2. TIMESTAMP_FORMAT ( expr_cadena, formato )

Page 194: IfxToJava2

194

Al igual que con Oracle esta función recibe el primer parámetro en formato cadena con lo cual habrá que convertir el valor que nos llegue a una cadena que represente una fecha/hora según la definición de la configuración local y sin perder precisión. Ej.:

TIMESTAMP_FORMAT(CHAR(expr_cadena, LOC), 'YYYY-MM-DD HH24:MI:SS')

El único formato que admite esta función es el indicado en el ejemplo.

Una función mas recomendable a utilizar es: TIMESTAMP ( expr_fecha/hora, formato ), la expresión fecha/hora puede venir en formato cadena o fecha/hora y el formato: �yyyy-mm-dd hh:mm:ss.ffffff�

MDY (mes, día, año ) Retorna un valor tipo DATE obtenido como resultado de evaluar las tres expresiones de tipo entero que recibe como parámetro. La primera representa el mes de 1 a 12, la segunda el día del mes de 1 a 31 y la tercera el año como un número de 4 dígitos.

Esta función no esta definida por el resto de gestores de bases de datos, pero si se puede obtener el mismo resultado utilizando para ello la combinación de varias funciones, a continuación se muestra el código a generar para cada gestor:

SqlServer: CONVERT (datetime, CONVERT (char(10), �dd/mm/yyyy�), 103) donde la cadena dd/mm/yyyy se debe construir en el momento de la ejecución, el valor 103 corresponde a la representación de fecha local según la tabla de formato de fechas proporcionada por SqlServer.

Oracle: TO_DATE (�dd/mm/yyyy�) donde la cadena debe construirse en tiempo de ejecución. El formato de la cadena dependerá de la configuración local.

Db2, usado la función: DATE (�dd/mm/yyyy�) donde la cadena se ha de construir en tiempo de ejecución y el formato de la misma dependerá de la configuración local.

En el Anexo I, apartado: Ejemplo funciones de manejo de fechas, se muestran ejemplos prácticos del tratamiento de funciones sobre fechas por parte del traductor. El ejemplo: Ejemplo de funcion weekday profundiza en la función weekday.

LENGTH ( quoted string | variable | tabla.columna ) Esta función retorna el número de caracteres de la cadena que recibe como parámetro si tener en cuenta los espacios en blancos al final de la misma.

Db2 y Oracle definen esta función con igual sintaxis pero semántica diferente, ya que para ambos gestores si tiene en cuenta los espacios al final de la misma. Para que el funcionamiento sea el mismo se añadirá la función RTRIM antes de aplicar la función LENGH, como se muestra a continuación: LENGTH (RTRIM( expr_cadena ) )

En el caso de SqlServer la sintaxis es diferente pero la semántica igual, la función a utilizar es: LEN ( cadena).

HEX ( int_expr ) Retorna el valor hexadecimal del entero que recibe como parámetro. Para obtener el mismo resultado en el resto de gestores de ha de hacer:

Para Oracle: TO_CHAR (expr_ entera ,'XXXXXXXX')

Db2 define la misma función HEX con igual sintaxis y semántica.

SqlServer no define la función HEX ni ninguna otra que realice esta operación. La solución que se adopta en este caso es definir una función en el gestor de bases de datos que realice dicha conversión. Esta función es:

drop function inttohex go Create function IntToHex(@Dec as bigint) --@Hex As varchar(8) Output) returns varchar(16) as begin Declare @HexDigits as char(16) declare @Hex as varchar(16) Set @HexDigits = '0123456789ABCDEF'

Page 195: IfxToJava2

195

Set @Hex = '' While @Dec >= 16 Begin Set @Hex = SubString(@HexDigits, (@Dec % 16) + 1, 1) + @Hex Set @Dec = @Dec / 16 End Set @Hex = SubString(@HexDigits, @Dec + 1, 1) + @Hex return @hex end go

Antes de ejecutar ningún programa que utilice la función HEX se debe de ejecutar este código sobre el gestor de bases de datos, para ello se abre un "SQL Query Analyzer" sobre la base de datos se copia dicho código en el mismo y se lanza.

ROUND (expr_sql [, número | 0] ) Este función proporciona como resultado el valor redondeado de la expresión que recibe como parámetro. Si se omite el número de dígitos decimales se redondea a 0 dígitos. El número puede ser un valor que va desde �32 hasta +32.

El resto de gestores definen esta función en algunos casos con alguna particularidad, pero siempre admitiendo la semántica de Informix-SQL. Oracle no contempla ninguna particularidad, Db2 y SqlServer si lo hacen, el primero no pone como opcional el número de dígitos a redondear y el segundo admite, de forma opcional un tercer parámetro que indica el modo de comportamiento de la función (0 o en blanco: redondea, 1 trunca). La sintaxis final a la que se traducirá esta sentencia en el código objeto será: ROUND (expr_sql , número ), donde número será 0 si en la definición original se omitía dicho parámetro.

TRUNC ( expr_sql [, número | 0] ) Devuelve el valor truncado de la expresión numérica que recibe como parámetro. Si se omite el número de dígitos decimales a dejar por defecto se entiende que es 0. El número puede ser un valor que va desde �32 hasta +32.

En este caso no todos los gestores de bases de datos aquí estudiados contemplan esta función, como es el caso de SqlServer, pero esto no será problema ya que la función ROUND de SqlServer admite un tercer parámetro que si se pone a 1 hará que se comporte como la función TRUNC. Para el resto de gestores pasa igual que con ROUND, Oracle la admite sin ninguna diferencia y Db2 la admite obligando a poner el segundo parámetro. El código generado, en función del gestor de base de datos destino, será:

Informix, Oracle, y Db2: TRUNC ( expr_sql , número ), número será 0 en el caso de que en el código fuente este valor se omita.

SqlServer: ROUND (expr_sql , número , 1)¸ donde número será 0 si en la sentencia original no había dicho parámetro.

En el apartado: Ejemplo de funciones matemáticas dentro del Anexo I se plasman casos prácticos del uso de las funciones matemáticas.

EXPRESIONES AGREGADAS

Las funciones agregadas permiten obtener información resumida de los datos de una tabla. Cuando se realiza una consulta a una tabla utilizando una función agregada el resultado será una simple fila conteniendo el dato solicitado.

Las funciones agregadas definidas por Informix-SQL son: COUNT, MAX, MIN, AVG, y SUM. A continuación se define el significado y sintaxis de las mismas y como se traducirán a código objeto, en caso de ser necesario, para ser ejecutadas sobre cualquier gestor de bases de datos de los aquí estudiados.

COUNT ( * | [ DISTINCT | UNIQUE ] [ nombretabla . ] nombrecolumna ) Retorna la cuenta del número de filas que satisfacen la condición WHERE de una sentencia SELECT. Si se incluye el nombre de una columna entonces esta función retorna el número total de valores no nulos para dicho campo. Si además se añade UNIQUE o DISTINCT retorna el número de valores únicos (no repetidos) no nulos para dicha columna. UNIQUE y DISTINCT son sinónimos.

Page 196: IfxToJava2

196

AVG ( [ ALL] expr_sql | [ DISTINCT | UNIQUE ] [ nombretabla . ] nombrecolumna ) Esta función retorna la media de todos los valorares de las seleccionadas en la columna o expresión.

MAX ( [ ALL] expr_sql | [ DISTINCT | UNIQUE ] [ nombretabla . ] nombrecolumna ) Retorna el valor máximo de la columna especificada o expresión.

MIN ( [ ALL] expr_sql | [ DISTINCT | UNIQUE ] [ nombretabla . ] nombrecolumna ) Retorna el valor mínimo de la columna especificada o expresión.

SUM ( [ ALL] expr_sql | [ DISTINCT | UNIQUE ] [ nombretabla . ] nombrecolumna ) Esta unción retorna la suma de los valores de la columna especificada o de la expresión.

Estas expresiones agregadas son soportadas por todos los gestores aquí estudiados y con la sintaxis original de Informix-SQL con la peculiaridad que el resto de gestores no reconocen el token UNIQUE en la misma. Esto no será problema ya que si en el código fuente aparece UNIQUE se sustituirá por DISTINCT en el código objeto generado.

En el punto: Ejemplo de funciones agregadas se muestran ejemplos de generación de código objeto de estas funciones para cada uno de los gestores de bases de datos estudiados.

NOMBRES DE VARIABLES

Con este titulo Informix hace referencia a el acceso a variables complejas: arrays y registros. La sintaxis que Informix define es:

<nombre_vbles> ::= <registro> | <array> <registro> ::= [ registro . ] [1..n] variable <array> ::= array [ número [,..n] ] [ . <nombre_vbles> ]

Es una sintaxis compleja pero admitida por cualquier gestor de bases de datos.

NOMBRES DE ELEMENTOS DE LA BASE DE DATOS Al definir la sintaxis, a lo largo de éste documento, se hace referencia a elementos de la base de datos como: tablas, vistas, sinónimos, índices, y constraints. Esto plantea dos dudas: que sintaxis representa y si ésta soportada por el resto de gestores de base de datos. Estas dos cuestiones se estudian a continuación:

La sintaxis de estos elementos es:

<ELEMENTOBD> ::= [ usuario .] nombretabla

Donde: usuario y nombretabla son dos identificadores.

Y esta sintaxis es soportada por el resto de gestores de bases de datos sin ninguna restricción.

Para hacer referencia a un campo de una tabla se usa la siguiente sintaxis:

<CAMPOTABLA> ::= [ <ELEMENTOBD> . ] nombrecampo

Esta sintaxis también es soportada por todos los gestores de bases de datos aquí estudiados, teniendo en cuenta la peculiaridad de oracle comentada en el apartado: Expresiones de manejo de columnas que si en la parte SELECT se indica el propietario de la tabla también se debe indicar en la parte FROM de la sentencia.

Page 197: IfxToJava2

197

OPERACIONES SOBRE EXPRESIONES SQL Sobre las expresiones de Informix-SQL se pueden aplicar una serie de operadores. La mayoría de los operadores tienen restricciones en cuanto a los tipos de datos sobre los cuales se pueden aplicar y los valores resultado de aplicarlos.

Las operaciones sobre expresiones SQL se definen sintácticamente al definir las condiciones y las expresiones como se muestra a continuación:

Definición sintáctica de las expresiones:

<expresión> ::= [ + | - ] <tipos_de_expresion> <mas_tipos_de_expresion> <mas_tipos_de_expresion> ::= [ [ + | - | * | / ] <tipos_de_expresion> <mas_tipos_de_expresion> ] | vacio <tipos_de_expresion> ::= [ <expresion_columna> | <expresion_cte> | <expresion_funcion> | <expresion_agregada> | <variable> | ( <expresión> ) ]

Las expresiones SQL así como su tratamiento ya han sido tratadas en el punto anterior: Expresiones sql.

Definición sintáctica de las condiciones:

<condición> ::= { [ NOT ] <condicion_de_comparacion> | <condicon_con_subquery> } [ AND | OR ] [..n] <condicon_de_comparacion> ::= <expresión> <operador_de_relacion> <expresión> | <expresión> [NOT] BETWEEN <expresión> and <expresión> | <expresión> [NOT] IN ( {literal_numerico | literal_fechahora | cadena_caracteres | TODAY | USER | CURRENT} [, ..n] ) | <campo> IS [NOT] NULL | <campo> [NOT] [LIKE | MATCHES] cadena_caracteres

<operador_de_relacion> ::= [ < | > | = | <= | >= | != | <> ]

<condicon_con_subquery> ::= <expresión> [NOT] IN (<sentencia_select>) | <expresión> [NOT] EXISTS (<sentencia_select>) | <expresión> <operador_de_relacion> [SOME|ANY|ALL] (<sentencia_select>)

Como se ve en la definición de la sintaxis las operaciones que se pueden realizar en el gestor de bases de datos son una combinación de expresiones y operadores. A continuación se detallan los operadores que admite Informix-SQL:

Operadores aritméticos se aplican sobre expresiones numéricas y son: +, -, *, y /. Si ambos operándoos son de los tipos de datos: INTEGER, SMALLINT o DATE el resultado de una operación aritmética será un número entero. Si un operando es del tipo de dato: DECIMAL, FLOAT, MONEY o SMALLFLOAT el valor resultante contendrá una parte fraccional.

Los operadores: + y � se pueden aplicar sobre operándoos tipo fecha. El resultado dependerá de los operándoos:

Si uno de los operándoos es un entero el resultado será una fecha siempre y cuando este dentro del rango de una fecha valida.

Si ambos son fechas el resultado será un entero negativo o positivo.

Operadores de relación son: <, <=, >, >=, =, <> y !=.

Operadores lógicos:

BETWEEN. Para que sea evaluada como cierta la expresión a la izquierda de la palabra reservada BETWEEN debe de estar incluida en el rango de valores de las dos expresiones de la parte derecha de la plabra reservada BETWEEN. Sintaxis:

Page 198: IfxToJava2

198

<expresion> [NOT] BETWEEN <expresion1> and <expresion2>

Otra forma equivalente de hacer la misma búsqueda es utilizando la siguiente sintaxis:

<expresion> >= <expresion1> AND <expresion> <= <expresion2>

Ejemplo:

select count(*) from prueba1 where campo2 between 1 and 2

IN. Una condición IN es satisfecha cuando la expresión de su parte izquierda esta incluida en la lista de elementos de la parte derecha, esta lista de elementos pueden ser literales separados por comas o bien el resultado de una sentencia select. Sintaxis:

<expresión> [NOT] IN ( {literal_numerico | literal_fechahora | cadena_caracteres | TODAY | USER | CURRENT} [, ..n] )

<expresion> [NOT] IN ( <sentencia_select> )

Ejemplos:

select campo3 from prueba1 where campo2 in (select campo2 from prueba2)

select campo3 from prueba1 where campo2 in (1,2,3)

IS. Permite chequear la presencia o ausencia de valores NULL. Sintaxis:

<campo> IS [NOT] NULL

Ejemplo:

select count(*) from prueba1 campo1 is null

LIKE, MATCHES. La condición de búsqueda es satisfecha cuando el valor de la columna indicado en la parte izquierda coincide con el patrón especificado en la cadena de caracteres. Sintaxis:

<campo> [NOT] [LIKE | MATCHES] cadena_caracteres

Si se usa la palabra reservada LIKE se pueden usar los siguientes caracteres espaciales dentro de cadena_caracteres:

% coincidencia con cero o más caracteres.

- coincidencia con un solo carácter.

\ elimina el significado especial del resto de caracteres especiales.

Si se usa la palabra reservada MATCHES se puede usar los siguientes caracteres especiales dentro de cadena_caracteres:

* coincidencia con cero o más caracteres.

? coincidencia con un solo carácter.

[�] coincidencia con los caracteres indicados dentro de los corchetes, admite rangos como [a-z]. Si el primer carácter es: ^ la coincidencia es con cualquier carácter excepto de los indicados entre corchetes.

\ elimina el significado especial del resto de caracteres especiales.

Cuando se realizan comparaciones de cadenas con LIKE/MATCHES, todos los caracteres de la cadena del modelo son importantes, incluidos los espacios iniciales o finales y la distinción entre mayúsculas y minúsculas. Si una comparación de una consulta debe devolver todas las filas con una cadena LIKE/MATCHES 'abc ' (abc seguido de un espacio), no se devuelve una fila en que el valor de esa columna sea abc (abc sin un espacio). Sin embargo, los espacios en blanco a la derecha de la expresión con la que se compara el modelo, se omiten. Si la comparación de una consulta debe devolver todas las filas con la

Page 199: IfxToJava2

199

cadena LIKE/MATCHES 'abc' (abc sin un espacio), se devuelven todas las filas que empiezan con abc y tienen cero o más espacios a la derecha.

EXISTS. La condición es evaluada a cierto cuando la subconsulta retorna al menos un valor. Sintaxis:

[NOT] EXISTS ( <sentencia_select> )

Ejemplo:

select campo3 from prueba1 where exists ( select * from prueba2 where campo2= prueba1.campo2)

ANY/ALL/SOME. La sintaxis es la siguiente:

<expresión> <operador_de_relacion> [SOME|ANY|ALL] (<sentencia_select>)

Si se usa el token ALL la expresión se evalúa a cierta si todos los elementos retornados por la subconsulta cumplen la comparación. Si no retorna ningún valor se evalúa cono cierta.

En caso de usar el token ANY la expresión se evalúa a cierto si al menos un valor de los devueltos por la sentencia select cumple la condición. Si la sentencia select no retorna ningún valor la expresión se evalúa como falsa.

SOME es un alias de ANY.

Ejemplo:

select sum(campo3) from prueba1 where campo2 any > (select campo2 from prueba2)

En la tabla siguiente se muestra la precedencia de operadores, que el gestor de bases de datos Informix soporta, en orden descendente (de mayor a menor precedencia). Los operadores con la misma precedencia se muestran en la misma fila:

Operador Propósito

+, - Operadores unarios: positivo, negativo.

*, / Operadores binarios: multiplicación, división.

+, - Operadores binarios: suma, resta.

NOT Negación.

<, <=, =, >, >=, !=, <> Operadores relacionales.

IN, BETWEEN, LIKE, MATCHES, SOME, ALL, ANY Operadores lógicos.

AND Conjunción.

OR Disyunción.

Tabla 41: Precedencia de operadores en Informix-SQL

TRATAMIENTO POR SQLSERVER

Para SQL Server un operador es un símbolo que especifica una acción que es realizada por una o más expresiones. SQL Server utiliza las siguientes categorías de operadores:

Operadores aritméticos: realizan operaciones matemáticas con dos expresiones de cualquiera de los tipos de datos de la categoría del tipo de datos numérico. Cuando se aplica un operador a dos expresiones de tipos de datos diferentes, las reglas de precedencia especifican cuál de los dos tipos se convierte al otro. El tipo de datos con menor precedencia se convierte al tipo de datos con mayor precedencia. Si la conversión no es una conversión implícita admitida, se

Page 200: IfxToJava2

200

devuelve un error. Cuando ambas expresiones de operándoos tienen el mismo tipo de datos, el resultado de la operación tiene ese tipo de datos5.

También se pueden utilizar los operadores de suma (+) y resta (-) para realizar operaciones aritméticas sobre valores datetime. Ej:

SET @startdate = '1/10/1900 12:00 AM'

SET @adddays = 5 SELECT @startdate + @adddays AS 'Add Date'

El resultado de sumar un número a una fecha es una fecha.

En SQLSERVER no se pueden restar fechas entre sí directamente como se puede hacer en Informix-SQL. Para solventar este problema a la hora de traducir el código objeto se debe de utilizar la función DATEDIFF como se muestra en el siguiente ejemplo:

Restar Fechas: DATEDIFF (dd, fecha1, fecha2)

Para saber si se debe utilizar esta función se necesitará determinar durante el análisis semántico que ambos partes de la expresión son de tipo DATE. Para poder determinarlo será preciso, en tiempo de traducción, tener conexión a la base de datos con objeto de obtener el tipo de datos de los campos.

Operador de asignación. Informix no considera este operador.

Operadores bit a bit. Los operadores bit a bit realizan tratamientos de bits entre dos expresiones de cualquiera de los tipos de datos de la categoría del tipo de datos enteros. No se profundiza más en este tipo de operador debido a que Informix-SQL no lo reconoce como tal y por tanto no habrá la necesidad de tratarlo a la hora de traducir código fuente a objeto.

Operadores de comparación. Los operadores de comparación comprueban si dos expresiones son iguales o no. Se pueden utilizar en todas las expresiones excepto en las de los tipos de datos TEXT, NTEXT O IMAGE. Es muy improbable que cause problemas este tipo de operaciones a la hora de ejecutar código destino sobre SQLSERVER ya que de estos tres tipos de datos solo se puede llegar a utilizar el tipo de dato TEXT y este contendrá cadena de tamaño grande (más de 254 caracteres) que es muy improbable se utilicen en comparaciones dentro de expresiones.

Devuelve un valor boolean: TRUE o FALSE.

Operadores lógicos. Los operadores lógicos comprueban la veracidad de alguna condición. Éstos, como los operadores de comparación, devuelven el tipo de datos boolean con valor TRUE o FALSE.

ALL/ANY/SOME. Sintaxis:

<expresión> {= | <> | != | > | >= | !> | < | <= | !<} [ALL|ANY|SOME] ( <subconsulta> )

ALL: Devuelve TRUE cuando la comparación especificada es TRUE para todas las parejas (scalar_expression, x) donde x es un valor del conjunto de columna única; de lo contrario, devuelve FALSE.

SOME o ANY: devuelve TRUE cuando la comparación especificada es TRUE para una pareja (scalar_expression, x) donde x es un valor del conjunto de resultados de una sola columna. De lo contrario, devuelve FALSE.

BETWEEN. Especifica el intervalo que se va a probar. Sintaxis:

<expresion> [ NOT ] BETWEEN <begin_expresion> AND <end_expresion>

5 Para más información sobre precedencia de operadores dirigirse a los libros en pantalla de Sql Server.

Page 201: IfxToJava2

201

BETWEEN devuelve TRUE (verdadero) si el valor de <expresión> es mayor o igual que el valor de <begin_expresion>, y menor o igual que el valor de <end_expression>.

EXISTS. Especifica una subconsulta para probar la existencia de filas. Sintaxis:

[NOT] EXISTS ( <subconsulta> )

Devuelve TRUE si alguna subconsulta contiene alguna fila.

IN. Determina si un valor dado coincide con algún valor de una subconsulta o lista. Sintaxis:

<expresion> [NOT] IN ( <subquery> | <expresion2> [ ,...n ] )

Si el valor de <expresión> es igual a cualquier valor devuelto por <subconsulta> o es igual a cualquier elemento de la lista separada por comas, el valor del resultado es TRUE. En caso contrario, el valor del resultado es FALSE.

Con NOT IN se niega el valor devuelto.

Hasta el momento los operadores lógicos estudiados para SQLSERVER tienen igual sintaxis que los que define Informix-SQL y un comportamiento igual con lo que no se plantea ningún problema a la hora de traducir código fuente a código objeto que pueda ser ejecutado sobre el gestor de bases SQL Server.

LIKE. Determina si una cadena de caracteres dada coincide o no con un determinado modelo. Un modelo puede incluir caracteres normales y caracteres comodín. Durante la coincidencia de patrones, los caracteres regulares deben coincidir exactamente con los caracteres especificados en la cadena de caracteres. Sin embargo, los caracteres comodín pueden coincidir con fragmentos arbitrarios de la cadena de caracteres. Con los caracteres comodín el operador LIKE es más flexible que los operadores de comparación de cadenas = y !=. Sintaxis:

<expresion> [ NOT ] LIKE <patron> [ ESCAPE escape_character ]

El patrón es el modelo que se va a buscar en <expresión> y puede incluir cualquiera de los siguientes caracteres comodín válido de SQL Server:

% Cualquier cadena de cero o más caracteres.

_ Cualquier carácter individual.

[] Cualquier carácter individual de intervalo ([a-f]) o del conjunto ([abcdef]) especificado.

[^] Cualquier carácter individual que no se encuentre en el intervalo ([^a-f]) o el conjunto ([^abcdef]) especificado.

Los caracteres comodín de concordancia de patrón se pueden utilizar como literales. Para utilizar como literal un carácter comodín, se incluye entre corchetes.

Con la opción ESCAPE se pueden buscar cadenas de caracteres que incluyan uno o más caracteres comodín especiales. Esta opción permite cambiar el carácter que se utiliza para utilizar los caracteres especiales en el patrón. Ejemplo: para buscar las filas que contengan la cadena 30% en cualquier parte de la columna, se puede especificar la cláusula WHERE siguiente: WHERE campo LIKE '%30\%%' ESCAPE '\'

SQL Server no define el operador MATCH pero define el operador LIKE de forma más completa que lo hace Informix-SQL lo cual facilitará el hacer la traducción de este operador de código fuente a código objeto.

Si en código fuente se utiliza el token MATCH en código objeto se utilizará LIKE, se analizará el patrón y se sustituirán los caracteres: * por % y ? por �, se mantendrá la utilización de corchetes para especificar conjuntos o rangos de caracteres. También se especificará la cláusula: ESCAPE '\' al generar código, en caso de que en el código fuente no se especifique y se utilice, con objeto de mantener el mismo carácter de escape.

Page 202: IfxToJava2

202

Si en código fuente se utiliza la cláusula LIKE a la hora de generar código objeto para SQLSERVER lo único que debe hacer para que el código objeto original sea compatible es especificar la cláusula: ESCAPE '\'

SqlServer, al igual que Informix-SQL, desprecia los caracteres blancos a la derecha de las palabras almacenadas en los campos a la hora de hacer comparaciones con la clausula LIKE.

Un problema que se plantea en este gestor de bases de datos es que los campos de la base de datos por defecto son case insensitive lo que implica que una comparación de una consulta que debe devolver todas las filas con una cadena LIKE �Abc� devolvería lo mismo que si la cadena LIKE fuese �abc� lo cual no es lo mismo que devolvería el gestor de bases de datos Informix-SQL para el cual se escribió el código original. SQLSever 2000 no plantea solución para este problema pero Sqlserver 2005 permite configurar el tratamiento de los campos por parte del gestor de dos formas diferentes: bien a través de la herramienta de administración del propio gestor de bases de datos en las propiedades de la misma, como se muestra en la siguiente figura, o bien a la hora de definir las campos de las tablas con la opción COLLATE, Ej.: create table prueba1 ( campo1 char(20) collate MODERN_SPANISH_CS_AI ). Por transparencia y sencillez esta configuración se hará a nivel de base de datos a través de la herramienta de administración.

Figura 13: Propiedades de la base de datos SQL Server

En el campo Intercalación se ha de fijar el valor: MODERN_SPANISH_CS_AI

SQLSERVER no define el operador lógico IN pero define la función IN que devuelve TRUE si dos objetos comparados son equivalentes, y FALSE en el resto de casos. Sintaxis:

<objeto1> IN <objeto2>

ó

<objeto1> IS [ NOT] NULL

Operador de concatenación de cadenas. El operador de concatenación de cadenas permite concatenar cadenas con el signo de suma (+), también conocido como operador de

Page 203: IfxToJava2

203

concatenación de cadenas. Cualquier otro tratamiento de cadenas se controla a través de funciones de cadenas como SUBSTRING.

En la versión de Informix que estamos traduciendo no se contempla este operador con lo que no habrá necesidad de utilizarlo a la hora de traducir código fuente a código objeto.

Operadores unarios. Los operadores unarios realizan una operación sobre una única expresión de cualquiera de los tipos de datos de la categoría del tipo de datos numérico.

Cuando una expresión compleja tiene múltiples operadores, la precedencia de operadores determina la secuencia en la que estos son evaluados. El orden de ejecución puede variar significativamente el resultado.

Los operadores tienen precedencia que se muestra en la tabla siguiente de mayor a menor precedencia. Los operadores de mayor precedencia son evaluados antes que aquellos de menor precedencia.

Operador Propósito

+, - , ~ Operadores unarios: positivo, negativo, negación a nivel de bit.

* , / , % Operadores binarios: multiplicación, división, módulo.

+ , - , + Operadores binarios: suma, resta, concatenación

=, >, <, >=, <=, <>, !=, !>, !< Comparación

^, &, | Comparación a nivel de bit: or exclusivo, and y or

NOT Negación lógica

AND Conjunción

ALL, ANY, BETWEEN, IN, LIKE, OR, SOME Operadores lógicos

= Asignación

Tabla 42: Precedencia de operadores en SqlServer

TRATAMIENTO PO ORACLE

Para oracle los operadores manipulan unidades de datos individuales llamados operándoos o argumentos. Los operadores se representan como caracteres especiales o palabras reservadas y Oracle los clasifica en los siguientes tipos:

Operadores aritméticos: Se utilizan en una expresión para negar, sumar, restar, multiplicar, o dividen valores numéricos. El resultado de una operación aritmética es un valor numérico. Algunos operadores se pueden utilizar sobre valores tipo DATE.

Oracle permite sumar o restar un valor tipo numérico a un valor tipo fecha o fecha/hora, proporcionando como resultado otro valor tipo fecha/hora. Oracle internamente convierte los valores tipo TIMESTAMP a valores tipo DATE e interpreta los valores numéricos como el número de días a aplicar sobre el operador. Si el valor numérico a es fraccional se entiende como el número de minutos. Ejemplos:

select sysdate + 1 from dual; Día siguiente.

select sysdate � 7 from dual; Semana pasada.

select sysdate + (10/1440) from dual; Suma 10 minutos.

Page 204: IfxToJava2

204

Oracle permite restar fechas retornando el número de días (positivos o negativos) que haya entre ambos operándoos.

Debido a que el tipo de dato DATE de Oracle contiene componente hora, Oracle permite que el resultado de una operación con fechas incluya y proporcione como resultado parte fraccional. Esta parte fraccional significa la porción de día. Ejemplo 1,5 días son 36 horas.

El comportamiento de Oracle con las operaciones sobre fechas, descrito anteriormente, es más amplio que el que define Informix-SQL debido a que: por un lado el tipo de datos DATE de oracle es más amplio al contener fechas y horas, y por otro a que Oracle permite sumar valores fraccionales a los valores tipo DATE. Esta mayor amplitud en la definición del tipo de dato DATE y las operaciones que se pueden hacer sobre él hace que la traducción de código fuente a código objeto ejecutable sobre Oracle no tenga ningún problema.

Operador de concatenación. El operador de concatenación manipula tipos de datos de cadenas de caracteres. El resultado de concatenar dos cadenas de caracteres es otra cadena de caracteres. En caso de que un parámetro sea de mayor rango (VARCHAR2, CLOB) que el otro el resultado se almacena sobre el de más rango estando limitada la longitud de la cadena resultante al la longitud del tipo de dato destino.

No es preciso utilizar este operador ya que la versión de Informix-SQL que se esta traduciendo no lo contempla.

Operadores de relación. Las condiciones de comparación comparan una expresión con otra. El resultado de dicha comparación es TRUE, FALSE o DESCONOCIDO.

Operadores lógicos.

SOME/ANY/ALL. Sintaxis:

<expresión> <operador_de_relacion> ( <subquerey> | <expresion_list> )

<operador_de_relacion> ::= < | > | <= | >= | != | = | <>

<expresion_list> ::= <expresión> [,..n]

SOME/ANY. Compara el valor con cada uno de aquellos devuelto en la <subconsulta>. Si en algún caso la condición de comparación se cumple el resultado de evaluar la expresión es TRUE. Si la <subconsulta> no retorna ninguna fila la expresión es evaluada como FALSE.

ALL. Compara el valor con todos los valores devueltos por la <subconsulta>. Si la condición se cumple para todos y cada uno de los valores retornados por la <subconsulta> la expresión se evalúa como TRUE. Si la <subconsulta> no retorna valores la expresión se evalúa como TRUE.

La sintaxis de este operador es totalmente compatible con la sintaxis de Informix-SQL con lo que no habrá ningún probleme al traducir código fuente a código objeto.

LIKE. Esta condición especifica una comparación con un patrón de caracteres. Sintaxis:

<expresion_de_caracteres> [NOT] LIKE patron [ ESCAPE caracter ]

Oracle evalúa la condición LIKE dividiendo el patrón en subpatrones que casan con uno o más caracteres cada uno. Los subpatrones que casan con más de un carácter se forman con uno de los siguientes caracteres de escape:

% Casa con uno o más caracteres.

- Casa con un único carácter.

La opción ESCAPE permite especificar dentro del patrón uno de los dos caracteres de escape anteriores sin que sean considerados como tal.

A la hora de traducir la sentencia LIKE del código fuente Informix-SQL a Oracle no se plantea ningún problema siempre y cuando se utilice la cláusula ESCAPE y el carácter de escape la barra invertida: �\�. En el caso de que en el código fuente se utilice la sentencia

Page 205: IfxToJava2

205

MATCHES, al igual que ocurría al traducir la sentencia para SqlSever, hay que sustituir el token MATCHES por LIKE y analizar el patrón y realizar sustituciones en el mismo: * por % y ? por -. Aquí se plantea un problema adicional debido a que la sentencia like no admite el patrón [].

Para solventar este problema, y conseguir así que el código resultante sea equivalente al código fuente, se propone como solución añadir una condición más a la sentencia en la cual se utilice la función SUBSTR, a continuación se muestras dos casos ilustrativos:

Código fuente Informix-SQL:

select campo1 from tabla1 where campo1 like �A[^B]C%�

Código objeto Oracle:

select campo1 from tabla1 where campo like �A_C%� and substr(campo1,2,1) != �B�

Código fuente Informix-SQL:

select campo1 from tabla1 where campo1 like �[A-C]E%�

Código objeto Oracle:

select campo1 from tabla1 where campo1 like �_E%� and substr(campo1,1,1) in (�A�,�B�,�C�)

Otro problema que se plantea sobre el gestor de bases de datos Oracle al aplicar la condición LIKE es que este considera los espacios en blanco al final de las cadenas debido a lo cual una condición de búsqueda LIKE �abc� (sin espacio al final) no casará con aquellos campos que contengan �abc � (con espacio al final) y esto no es el comportamiento del gestor original. Para solucionar este problema se han planteado dos soluciones: bien aplicar la función RTRIM sobre el campo o bien añadir al final de la cadena patrón un %. Aunque se entiende que es más correcta la primera solución se implementa la segunda por sencillez en su tratamiento.

BETWEEN. Comprueba sin una expresión esta incluida en un rango. Sintaxis:

<expresion> [NOT] BETWEEN <expresion1> AND <expresion2>

La sintaxis de está sentencia es totalmente compatible con la de Informix-SQL.

IS. Permite comprobar si la expresión es NULL. Sintaxis:

<expresión> IS [NOT] NULL

No se plantea ningún problema con esta sentencia al traducir código fuente Informix-SQL a Oracle.

EXISTS. Testea la existencia de filas en la subconsulta. Sintaxis:

EXISTS ( <subconsulta> )

Informix-SQL define la misma sintaxis para esta sentencia.

IN. Chequea sin una expresión esta incluida en a una lista o subconsulta. Sintaxis:

<expresion> [NOT] IN { <expresion_list> | <subquery> }

Esta sentencia no plantea ningún problema a la hora de traducir código fuente a código objeto.

En la tabla siguiente se muestran los operadores utilizados por oracle así como la precedencia de los mismos. A la hora de evaluar condiciones en la misma expresión, Oracle evalúa las condiciones con mayor precedencia antes que aquellas de menor precedencia. Las condiciones de igual precedencia son evaluadas de izquierda a derecha.

Los operadores son evaluados antes que las condiciones SQL.

Page 206: IfxToJava2

206

En la tabla que se muestra a continuación se listan los niveles de precedencia en comparaciones de mayor a menor. Las condiciones en la misma línea tienen la misma precedencia

Operador Propósito

+, - Operadores unarios: positivo, negativo.

*, / Operadores binarios: multiplicación, división.

+, -, || Operadores binarios: suma y resta, concatenación.

=, !=, <, >, <=, >=, <> Comparación.

IS [NOT] NULL, LIKE, [NOT] BETWEEN, [NOT] IN, EXISTS, IS OF type, SOME, ANY, ALL

Comparación lógica.

NOT Negación lógica

AND Conjunción.

OR Disyunción.

Tabla 43: Precedencia de operadores Oracle

TRATAMIENTO POR DB2

Las expresiones son el elemento básico de construcción de querys. Las expresiones puedes utilizarse solas o junto con otras expresiones para construir querys complejas. Los tipos de expresiones básicos son:

Expresiones aritméticas, incluye los operadores unarios: + y � y +, -, *, y / binarios. El resultado de realizar una operación aritmética sobre dos valores validos es un valor numérico.

Al igual que en Informix-SQL se pueden aplicar los operadores + y � sobre fechas, permitiéndose incrementar, decrementar fechas y restar:

Sumar o restar un valor numérico a una fecha. El resultado es una fecha que corresponde a la fecha que se recibe como operando +/- el número el cual se interpreta en función de la definición de la �duración�. Db2 no deja sumar valores numéricos directamente a fechas, estos deben de venir precedidos de la etiqueta de duración. La etiqueta de duración representa la unidad de tiempo en la cual se expresa el número. Las palabras que se pueden utilizar para indicar la duración son: YEARS, MONTHS, DAYS.

Para ser capaces de traducir código fuente Informix a Db2 que incluya esta operación será preciso un tratamiento semántico de la expresión, y este tratamiento implicará la necesidad de, en tiempo de traducción, tener conexión a la base de datos con objeto de determinar el tipo del campo que se procesa en la expresión. Ejemplo:

código fuente: select campo4 + 1 from tabla

código objeto Db2: select campo4 + 1 DAY from tabla

Para realizar la conversión de código de forma correcta se requiere del análisis semántico con objeto de determinar, en tiempo de traducción, el tipo de datos de las variables, constantes y/o campos.

Restar fechas. El resultado de restar una fecha de otra es un valor entero, positivo o negativo, que represente el número de años, meses y días entre ambos operándoos. Db2 representa el resultado en un tipo de dato decimal(8,0) donde, empezando de izquierda a derecha, los dos primeros dígitos representan los días los, dos siguientes los meses y el resto los años de diferencia entre ambas fechas. Ej: El resultado de restar las fechas �15/03/2000� y �31/12/199� es 00000215 que representa: 0 años, 2 meses y 15 días.

Page 207: IfxToJava2

207

El valor devuelto por Db2 al ejecutar el operador de resta (-) no es coherente con el que proporciona el gestor de bases de datos Informix-SQL, para que ambos gestores retornen el mismo valor se habrá modificar el código generado para Db2 de la siguiente forma:

código fuente: select campo2 � campo1 from tabla1

código objeto: select days(campo2) � days(campo1) from tabla

Evidentemente se ha de saber en tiempo de compilación los tipos de datos de los operándoos. Esto nos lo proporcionará el analizador semántico.

Expresiones lógicas usan los operadores AND y OR para, tras ser aplicados sobre los operándoos, proporcionar un valor booleano (TURE o FALSE).

Expresiones de comparación.

En DB2 se pueden combinar querys con diferentes conjunto de operadores para construir sentencias condicionales complejas.

Una condición de búsqueda esta formada por uno o más predicados. Un predicado especifica una condición sobre una fila que puede ser evaluada como: TRUE, FALSE o UNKNOWN.

Dentro de la cláusula WHERE se pueden usar los siguientes predicados:

Predicados básicos: <, <=, =, >, >=, <> permiten comparar dos valores. Sintaxis:

<expresión> [ = | <= | >= | < | > | <> ] <expresión>

Predicados Cualificados: ANY, SOME, ALL. Permiten comparar uno o más valores con una colección de valores. Sintaxis:

<expresión> <operador_relacion> {SOME|ANY|ALL} ( <subconsulta> )

| <expresiones> {SOME|ANY} ( <subconsulta> )

Cuando se utiliza ALL el resultado de evaluar el predicado es TRUE si la <subconsulta> no retorna valores o la comparación entre la expresión y los valores devueltos por la <subconsulta> se evalúa a TRUE para todos ellos.

Si se especifica SOME o ANY el predicado es evaluado a TRUE si la condición se cumple para al menos una fila de las retornadas en la <subconsulta>. Si la <subconsulta> no retorna ninguna fila la expresión se evalúa a FALSE.

Esta sintaxis, aunque más amplia, es totalmente compatible con la definida por Informix-SQL.

Predicado BETWEEN. Compara un valor con un rango de valores. Sintaxis:

<expresion> [NOT] BETWEEN <expresion1> AND <expresion2>

sintaxis compatible con la de Informix-SQL.

Predicado EXISTS. Comprueba la existencia de alguna fila en la subconsulta. Sintaxis:

EXISTS ( <subconsulta> )

Sintaxis compatible con la de Informix-SQL.

Predicado IN. Compara un valor o conjunto de valores con una colección de valores. Sintaxis:

<expresion> [NOT] IN { ( <subquery> ) | <expresion2> | ( <expresion2> [,..n] ) }

| <expresion> [,..n] [NOT] IN ( <subquery> )

La sintaxis de esta sentencia es más amplia que la definida en Informix-SQL pero incluye ésta con lo que no habrá ningún problema para al ejecutar esta sentencia sobre el gestor de bases de datos DB2.

Page 208: IfxToJava2

208

Predicado LIKE. Este predicado busca una cadena de caracteres que cumpla un cierto criterio. El patrón es otra cadena de caracteres en la cual los caracteres: - y % tienen un significado especial. Sintaxis:

<expresion> [NOT] LIKE <patron> [ESCAPE <expresion_escape>]

El patrón utilizado para definen el criterio a aplicar a la expresión puede contener los siguientes caracteres:

Carácter de subrayado (_) representa cualquier carácter simple.

Carácter de porcentaje (%) representa una cadena de 0 ó más caracteres.

Cualquier otro carácter se representa así mismo.

Si dentro del patrón se necesita incluir un carácter especial (_, %) como un carácter normal se debe de utilizar cláusula ESCAPE. El carácter indicado en esta cláusula ha de preceder al carácter especial que se desea utilizar como carácter normal dentro del patrón.

A la hora de traducir código fuente Informix-SQL para ser ejecutado sobre el gestor de bases de datos DB2 con esta sentencia se plantean los mismos problemas que con Oracle: no admite el definir un grupo de caracteres o la exclusión dentro del patrón y considera los caracteres en blanco al final de la cadena a la hora de comparar con el patrón LIKE. La solución planteada, para cada uno de los casos, será la misma que se aplico para Oracle.

Predicado NULL. Testea la existencia de valores NULL. Sintaxis:

<expresión> IS [NOT] NULL

Esta sentencia es equivalente a la definida por Informix-SQL.

En la siguiente tabla se muestra los operadores de DB2 en orden de mayor a menor precedencia:

Operador Propósito

+, - Operadores unarios: positivo, negativo.

*, / Operadores binarios: multiplicación, división.

+, - Operadores binarios: suma, resta.

SOME, ANY, ALL

NOT Negación.

<, <=, =, >, >=, <> Operadores de comparación.

EXISTS, IN, BETWEEN, LIKE, MATCHES Operadores lógicos.

AND Conjunción.

OR Disyunción.

Tabla 44: Precedencia de operadores Db2

TRADUCCIÓN DE OPERADORES SOBRE EXPRESIONES

Al operar con fechas hay que tener en cuenta la definición de las mismas. Oracle y SqlServer definen los tipos de datos DATE y SMALLDATETIME respectivamente para almacenar fechas, estos tipos de datos contienen información de la fecha y de la hora lo cual difiere con la definición que realiza Informix (y DB2) la cual solo contiene información sobre la fecha. Esto podría producir errores a la hora de operar y hacer comparaciones como en los ejemplos que se muestran a continuación:

Ejemplo1, restar un campo tipo fecha con la constate today:

Código fuente: select campo1 � today into entero from tabla

Page 209: IfxToJava2

209

Código fuente SqlServer: select campo1 � getdate() into entero from tabla

Código fuente SqlServer: select campo1 � sysdate into entero from tabla

Dependiendo de la hora del día el valor de la variable: entero para la consulta realizada para SqlServer y Oracle podría ser el mismo que para Informix o un día menos.

Ejemplo2, comparar fechas:

Código fuente: select count(campo2) from tabla where campo1 = today

Código fuente SqlServer: select count(campo2) from tabla where campo1 = getdate()

Código fuente SqlServer: select count(campo2) from tabla where campo1 = sysdate

Lo más normal es que la consulta que se realiza sobre el gestor de base de datos Informix proporcione un valor entero positivo y la realizada sobre SqlServer y Oracle de 0.

Por otro lado para que las operaciones sobre fechas tengan el mismo significado sobre todos los gestores habrá que realizar, a la hora de generar código objeto para SqlServer y Oracle, para aquellas sentencias que definen valores para este tipo de variables/campos es que la parte hora tome el valor 0:0:0. Este caso se dará básicamente a la hora de traducir la constante TODAY a estos gestores. La traducción a realizar será:

Para Oracle en lugar de usar SYSDATE utilizar: TO_DATE(TO_CHAR(SYSDATE,'dd/mm/yyyy'))

Para SqlServer en lugar de usar GETDATE() utilizar: DATEPART(dd,0, DATEDIFF(dd,0,GETDATE()))

Para poder traducir las operaciones de que involucran fechas a otros gestores hay que aplicar mucha semántica y utilizar la tabla se símbolos. Es preciso saber el tipo de datos de los operandos que intervienen en la expresiones y para saber estos es necesario identificar los tipos a los que pertenecen las constantes, variables y campos de las tablas y para estos últimos es necesario saber a que tabla pertenecen los campos.

El primer problema para determinar el tipo de dato de un campo es que en alguna sentencia, sentencia select por ejemplo, el nombre de la tabla se lee con posterioridad al nombre de los campos y a la hora de procesar los campos se debe de saber el tipo de estos. La solución a este problema es hacer una lectura hacía delante de tokens hasta determinar las tablas y/o sinónimos que intervienen en la sentencia. Una vez sabido el nombre de las tablas que intervienen en la sentencia ya se puede determinar el tipo de datos de los campos haciendo una consulta a la base de datos.

Dentro del Anexo I, en la sección: Ejemplo de manejo de operaciones sobre expresiones se plasma un ejemplo completo del comportamiento del traductor ante los distintos operadores y atendiendo al gestor de bases de datos destino.

CONFIGURACIÓN LOCAL No se pretende en esta sección explicar como se ha de configurar los diferentes gestores de bases de datos a nivel de idioma, formatos, fechas, etc., sino: por un lado saber como son reconocidos los literales por cada uno de los gestores de bases de datos, aquí estudiados, para garantizar que un literal definido en el código fuente Informix-SQL sea también reconocido de la misma manera por el gestor de base de datos sobre el que se ejecute, y por otro lado poner los medios necesarios para garantizar que la interpretación de los literales que hace Informix-SQL sea la misma que realicen el resto de gestores, por ejemplo si tenemos la fecha �12/6/2006� Informix la interpreta como el 6 de diciembre de 2006 es por tanto necesario si queremos que el código fuente pueda ser ejecutado, con el mismo significado semántico, sobre el resto de gestores que estos la interpreten de la misma forma. Pongamos un ejemplo:

Si en el campo: campofecha de la tabla: tablaY tenemos el valor: 30 de diciembre de 2005 y ejecutamos la siguiente sentencia:

Select campotipofecha � �12/01/2006� into vble from tablaY

Page 210: IfxToJava2

210

El resultado de esta sentencia ejecutado sobre el gestor de bases de datos Informix, suponiendo que este interpreta la fecha como dd/mm/yyyy, será �13, pero si ejecutamos esta misma sentencia sobre un gestor de bases de datos que interprete la fecha como mm/dd/yyyy el resultado será �336 y por tanto la ejecución del programa obtendrá resultados diferentes a los esperados.

Los elementos clave a considerar son: delimitares de cadena y fecha, formato de fecha, separador de campo dentro de la fecha, delimitador de decimales, número de día de la semana, etc.

Para ello se empezara indicando la configuración que tiene Informix-SQL por defecto, algunas variables de entorno que fijan/modifican dicha configuración, posteriormente se estudiara como definen y en base a que estos elementos de la configuración el resto de gestores de bases de datos para con ello determinar los puntos a tener en cuenta para que el resto de gestores interpreten de igual forma, que Informix, los literales.

ELEMENTOS DE INFORMIX

En Informix-SQL hay elementos que definen la configuración de los literales que vienen fijados por el idioma como por ejemplo el formato de fecha, separador decimal, etc., pero también existen otros que son fijos como el delimitador de cadenas, el número asociado al día de la semana, etc. Estos elementos se definen a nivel de gestor de bases de datos y algunos de ellos pueden ser modificados a nivel configuración de sesión de usuario.

Por defecto Informix tiene la siguiente configuración:

Elemento Delimitador

Delimitador de cadenas o fechas Comilla doble ó comilla simple

Delimitador de decimal Punto

Formato de fecha mm/dd/yyyy

Formato fecha/hora yyyy-mm-dd hh:mm:ss.ffffff

Delimitador fecha Flash (/)

Días de la semana 0 domingo, 1 lunes, ...., 6 sábado

Tabla 45: Formatos por defecto de Informix-SQL

De estos valores, el día de la semana y el formato de fecha/hora no dependen del idioma configurado para el gestor ni de ninguna otra variable del servidor o de la sesión actual, su configuración es siempre la misma.

Existe un grupo de variables de entorno a nivel de sesión de usuario que pueden cambiar el comportamiento por defecto del gestor para cada usuario, estas son:

DBDATE. Variable que permite especificar a los usuarios finales el formato de los valores tipo fecha. Con esta variable se indica:

Orden del Mes (M), día (D), y año (Y) en la fecha.

Número de dígitos para el año: Y2 (dos dígitos) , Y4 (cuatro dígitos)

Separador entre los valores de la fecha, valor por defecto /, si se pone 0 (cero) se entiende que no hay.

Ejemplos:

MDY4/ 07/01/1950 DMY2- 01-07-50 MDY4/ 07/01/1950 MDY20 070150

Page 211: IfxToJava2

211

DBCENTURY. La parte año de las fechas puede ser introducida con dos o con cuatro dígitos. Si el valor es expresado con dos dígitos la centuria se calcula en función del valor de esta variable de entorno. Lo posibles valores que puede tomar son:

P = Pasado; asume que la fecha ambigua es pasada.

F = Futuro; asume que la fecha ambigua es futura.

C = Cercano; las fechas pasadas, presentes y futuras son evaluadas como lo mas cercana a la fecha actual.

R = Presente; una fecha ambigua se entiende que es de la centuria actual.

Si esta variable no esta fijada se entiende que tiene el valor R ósea la fecha se evalúa como de la centuria actual.

DBMONEY. Indica el delimitador decimal y por omisión el separador de miles.

DBDELIMITER. Indica el valor delimitador de los campos de las tablas en las descargas y cargas de datos a y desde ficheros.

ELEMENTOS DE SQLSERVER

En SqlServer la opción de lenguaje por defecto establece el formato de mensajes, nombres de meses, días de la semana, fechas y otras características relativas a la localización. A la hora de instalar el servidor de bases de datos se elige el lenguaje del mismo que por defecto será el que tendrán los usuarios. El lenguaje que se tiene en cuenta es el que se establece para cada login y puede cambiarse si se desea.

Con el idioma por defecto: Ingles, los valores que asume este gestor son:

Elemento Delimitador

Delimitador de cadenas o fechas Comilla simple

Delimitador de decimal Punto

Formato de fecha mm/dd/yyyy (mdy)

Formato de fecha/hora yyyy-mm-dd hh:mm:ss.fff

Delimitador fecha slash (/)

Días de la semana 1 domingo, 2 lunes, ...., 7 sábado

Tabla 46: Formatos por defecto de SqlServer

Los formatos en los que se presentan las fechas pueden ser:

dma (día, mes año) formato si el idioma es español.

mda (mes, día, año) formato por defecto.

amd (año, mes, día)

Para el caso de días de la semana si el idioma del usuario que se conecta fuese español tomaría los valores: 1 lunes, 2 martes, ..., 7 domingo. Para este gestor este valor, al igual que el formato de fecha, depende del idioma del login del usuario y variará en función de este.

Sin tener que cambiar el idioma existe posibilidad de cambiar alguno de estos parámetros como el formato de fecha y el orden de los días de la semana, para ello se pueden usar las variables de SqlServer: DATEFORMAT y DATEFIRST6.

6 Ver Documntación de SQL Server

Page 212: IfxToJava2

212

ELEMENTOS DE ORACLE

En Oracle existen varias variables que dependen del idioma seleccionado, estas se basan en el conjunto de caracteres de la base de datos actualmente definido para un servidor, cliente o sesión. Están variables son las que definen los formatos de fecha, días de la semana, idioma de los mensajes, etc., y son conocidas como parámetros NLS. El idioma se fija por primera vez a la hora de instalar el servidor.

Hay muchas formas de establecer los parámetros NLS tanto para el cliente como para el servidor:

Se pueden especificar los parámetros NLS en el archivo de inicialización de la base de datos en el servidor (init.ora). Esta configuración no tiene ningún efecto en el lado del cliente, solo en el comportamiento del servidor.

Se pueden establecer los parámetros NLS como una variable de entorno en el cliente. Esto define el comportamiento del cliente y modifica los definidos al momento de iniciar la sesión en el archivo de parámetros.

Se pueden cambiar los parámetros NLS para una sesión con el comando: alter session set ...

Y se pueden cambiar parámetros NLS incluso dentro de alguna sentencia SQL.

Los valores de los parámetros por defecto dependen del lenguaje elegido a la hora de hacer la instalación o bien el del sistema operativo sobre el que se instala el gestor. En el caso de que el idioma sea español estos valores son:

Elemento Delimitador

Delimitador de cadenas o fechas Comilla simple

Delimitador de decimal Punto

Formato de fecha dd/mm/yyyy

Formato de fecha/hora yyyy-mm-dd hh:mm:ss.fffffffff

Delimitador fecha slash , guión, punto, espacio en blanco, etc.

Días de la semana 1 lunes, ...., 7 domingo

Tabla 47: Formatos por defecto de Oracle

Una forma de ver la configuración actual de cada sesión que se inicia contra el servidor es consultar, vía sqlplus, la tabla: nls_sesssion_parameters que nos proporcionará los valores que tomara cada usuario al iniciar sesión, como se muestra a continuación:

SQL> select * from nls_session_parameters; PARAMETER VALUE ------------------------------ ------------------------------ NLS_LANGUAGE SPANISH NLS_TERRITORY SPAIN NLS_CURRENCY Pts NLS_ISO_CURRENCY SPAIN NLS_NUMERIC_CHARACTERS , NLS_CALENDAR GREGORIAN NLS_DATE_FORMAT DD/MM/YY NLS_DATE_LANGUAGE SPANISH NLS_SORT SPANISH NLS_TIME_FORMAT HH24:MI:SSXFF NLS_TIMESTAMP_FORMAT DD/MM/YY HH24:MI:SSXFF NLS_TIME_TZ_FORMAT HH24:MI:SSXFF TZH:TZM NLS_TIMESTAMP_TZ_FORMAT DD/MM/YY HH24:MI:SSXFF TZH:TZM NLS_DUAL_CURRENCY ¤ NLS_COMP

Page 213: IfxToJava2

213

Una forma sencilla de cambiar un parámetro para un cliente en particular es fijárselo como variable de entorno, ejemplo: set NLS_DATE_FORMAT=�MM/DD/YYYY�, en programas java se puede ejecutar la sentencia: alter session set NLS_DATE_FORMAT=�MM/DD/YYYY�.

Para documentarse en mayor profundidad sobre los valores a configurar en los diferentes parámetros NLS referirse a la documentación proporcionada por Oracle.

ELEMENTOS DE DB2

Cuando se crea una base de datos en DB2 se ha de decidir en que lenguaje serán almacenados los datos en ella. Al crear la base de datos se ha de especificar el territorio y conjunto de códigos, los cuales pueden ser diferente del que tenga configurado el sistema operativo sobre el cual se esta instalando el gestor de bases de datos. Si no se especifica de forma explícita en el momento de la creación de la base de datos el lenguaje con el cual se creará esta vendrá determinado por la configuración local.

La configuración local de los usuarios que acceden a la base de datos a de ser compatible con la que tenga el servidor. El idioma local se puede fijar en el script de inicialización del usuario (profile, autoexec.bat, variables de entorno) y para ello se usa la variable de entorno LANG.

La representación de literales de fecha y hora, el delimitador de decimales, y otros elementos que dependen del código de territorio (idioma) que se fija en el entorno de usuario a través de la variable LANG.

Con el idioma por defecto: Español igual al sistema operativo en el cual esta instalado, los valores que asume este gestor son:

Elemento Delimitador

Delimitador de cadenas o fechas Comilla simple

Delimitador de decimal Punto

Formato de fecha dd/mm/yyyy

Formato de fecha/hora yyyy/mm/dd hh:mm:ss.fffff

Delimitador fecha slash (/)

Días de la semana 1 domingo, 2 lunes, ...., 7 sábado

Tabla 48: Formatos por defecto de Db2

De estos elementos hay algunos que son fijos, que no dependen del idioma, como son: el delimitador de literales y el número asociado a cada día de la semana, etc.

Para más información referirse a la documentación proporcionada por IBM respecto a su gestor de bases de datos DB2.

ELEMENTOS DE JAVA

Algo muy normal dentro de un programa es que se produzca el intercambio de valores: variables o constantes, entre el entorno de programación y el gestor de bases de datos. Por tanto se debe de tener claro como interpreta java los elementos de la configuración local para así poder garantizar que el traspaso de código fuente informix a objeto java mantenga la misma coherencia sobre estos elementos que cuando se escribió.

A la hora de representar fechas en java se utilizará la clase java.sql.Date o java.sql.Timestamp dependiendo del tipo de dato a almacenar. Las constantes predefinidas en java no están condicionadas por el idioma como ocurre con los gestores de bases de datos. Su definición se muestra en la siguiente tabla:

Elemento Delimitador

Delimitador de cadenas o fechas Comilla doble

Page 214: IfxToJava2

214

Delimitador de decimal Punto

Formato de fecha yyyy-mm-dd

Formato de fecha/hora yyyy-mm-dd hh:mm:ss.fffffffff

Delimitador fecha guión (-)

Días de la semana 1 domingo, 2 lunes, ...., 7 sábado

Tabla 49: Formatos del lenguaje de programación Java

Los valores tipo fecha son almacenados en variables tipo java.sql.Date y la función estática valueOf permite reconocer cadenas de texto con el formato: "yyyy-mm-dd" y transformarla en valores tipo Date. En este caso la cadena de caracteres de entrada ha de ser preprocesada ya que el formato original no suele cumplir este formato. Si se asocia a un campo tipo java.sql.Date un valor entero hay que tener en cuenta que una variable tipo date representa, como long, el número de milisegundos desde el 1 de enero de 1970 con lo cual será preciso aplicar un valor de corrección al valor numérico que aparece en el código fuente puesto que este representará el número de días desde el 31/12/1899.

Los valores constantes tipo fecha/hora son reconocidos por la clase java.sql.Timestamp y la función estática valueOf permite transformar una constate con el formato: yyyy-mm-dd hh:mm:ss.fffffffff a una variable tipo TimeStamp.

Utilizando la función valueOf se consigue que java reconozca en variables tipo Date o Timestamp definidas en el código fuente Informix-4GL y en el estudio realizado en el apartado: Mapeo de tipos de datos entre Jdbc y java se sustenta el intercambio de datos fecha y fecha/hora entre este tipo de variables Java y el gestor de base de datos.

Cada día de la semana tiene asociado una constante estática entera en la clase java.util.Calendar de tal forma que java.util.Calendar.SUNDAY es 1, java.util.Calendar.MONDAY es 2 y así sucesivamente hasta java.util.Calendar.SATURDAY vale 7. Para que esta constante tenga el mismo significado que tenía en el código fuente se le ha de restar el valor 1.

CONCLUSIONES Y EJEMPLO DE CONFIGURACIÓN

Según lo visto en los puntos anteriores se constata que existen elementos que, en función del gestor de base de datos, dependen del idioma en el cual este configurado el servidor, base de datos, clientes o usuarios, y estos elementos no son los mismos para cada gestor. Por ejemplo el delimitador de cadenas de caracteres es un valor que no depende en ningún gestor de la configuración del mismo, existen otros como el número asociado al día de la semana que en algunos casos si depende y en otros no, y otros valores que siempre dependen de la configuración de idioma como es el formato de fecha.

Lo que esta claro es que lo que se debe conseguir es que los formatos que se mantenían en el gestor original y por tanto en el código fuente original han de ser reconocidos de forma correcta por el resto de gestores y para eso se deben de hacer los cambios oportunos por un lado en la configuración de los gestores sobre los cuales se pretende ejecutar el código generado y por otro lado se ha de generar código para atender a las peculiaridades que tiene cada gestor.

Supongamos que Informix, gestor original, esta configurado con el idioma Ingles y formato de fecha dd/mm/yyyy, que SqlServer esta instalado en Ingles y con el usuario de conexión en idioma Español y Oracle y Db2 en Español. Los formatos que define cada gestor se muestran en la siguiente tabla:

Elementos de formato Informix SqlServer Oracle Db2

Delimitador de cadenas Comilla simple/doble

Comilla simple Comilla simple Comilla simple

Delimitador de decimal

Punto Punto Punto Punto

Page 215: IfxToJava2

215

Formato de fecha

dd/mm/yyyy dd/mm/yyyy dd/mm/yyyy dd/mm/yyyy

Formato fecha/hora yyyy-mm-dd hh:mm:ss.ffffff

Delimitador fecha

slash slash slash slash

Días de la semana 0 domingo, 1 lunes, ...., 6 sábado

1 lunes, 2 martes, ...., 7 domingo

1 lunes, 2 martes, ....., 7 domingo

1 domingo, 2 lunes, ...., 7 sábado

Tabla 50: Ejemplo de configuración de entornos

Observando la tabla vemos tres problemas:

Delimitador de Cadenas de caracteres. Informix admite la comilla doble y el resto de gestores no. Esto en sí no es ningún problema ya que Informix admite también la comilla simple con lo cual a la hora de generar código objeto toda comilla doble, del código fuente, será sustituida por comilla simple.

Sqlserver interpreta las fechas de forma diferente que el gestor para el cual esta escrito el código fuente original. La solución aquí es sencilla, se cambia el idioma del usuario que va a ejecutar el código destino a español.

La interpretación de los días de la semana. SqlServer y Oracle lo hacen en función de la configuración del idioma establecido para el usuario/sesión que se conecta a la base de datos; sin embargo para Informix y DB2 estos valores son siempre los mismos.

Así, si el Idioma es Ingles (-1), SqlServer y Oracle proporcionan como días: lunes: 2, martes: 3, miércoles: 4, jueves: 5, viernes: 6, sábado: 7, y domingo: 1. Pero si el idioma es español (%7) proporcionan: lunes: 1, martes: 2, miércoles: 3, jueves: 4, viernes: 5, sábado: 6, y domingo: 7.

Viendo estos posibles resultados y teniendo en cuenta los que ofrece Informix lo que se ha de hacer, a la hora de traducir el código fuente a código objeto aplicable sobre otros gestores, es que el resultado sea el mismo que el que daría Informix en todo caso lo cual permitirá que los programas originales corran sobre cualquier gestor con la mima semántica con la que fueron diseñados. Para ello será necesario por aplicar correcciones a los resultados que proporcionan el resto de gestores para lo cual será preciso, para los casos de los gestores de bases de datos Oracle y SqlServer saber con que idioma trabaja el usuario/sesión.

El idioma con que trabajan los usuarios/sesiones será un parámetro del fichero de configuración de la conexión, ver apartado: ¡Error! No se encuentra el origen de la referencia.

Los casos que se pueden dar son:

Día de la semana en formato Ingles (1 domingo, 2 lunes, � 6 viernes, 7 sábado). En este caso en la traducción del código fuente habría que, además de cambiar la función a ejecutar, restarle uno para que la ejecución de la sentencia tenga el mismo significado que cuando se diseño. Ej.:

Código original:

select weekday(campoX) into vble from tablaY #si es domingo if vble = 0 then .....

Sentencia final:

select funciondiadelasemana ( campoX) �1 into vble from tablaY #si es domingo if vble = 0 then .....

Día de la semana en formato Español (1 lunes, 2 martes, � 6 sábado, 7 domingo). En este caso la formula que nos pasaría el resultado generado por el gestor a un valor comparable

Page 216: IfxToJava2

216

con una constante, que representa el número de día de la semana, del código fuente sería la función mod, como se muestra a continuación:

Código original:

select weekday(campoX) into vble from tablaY #si es domingo if vble = 0 then .....

Sentencia final:

select funciondiadelasemana ( campoX) mod 7 into vble from tablaY #si es domingo if vble = 0 then .....

Como ejemplo práctico para el caso de que el idioma especificado, en aquellos gestores en los que el día de la semana no es fijo, sea español la traducción el código fuente a objeto quedaría:

Código original:

select weekday(campoX) into vble from tablaY #si es domingo if vble = 0 then .....

Sentencia final:

SqlServer:

select ( datepart(gw, campoX) % 7) from tablaY #si es domingo if vble = 0 then .....

Oracle:

select mod( campoX,'D') , 7) from tablaY; #si es domingo if vble = 0 then .....

Db2:

select campoX,'D') - 1 from tablaY; #si es domingo if vble = 0 then .....

Como conclusión para el manejo correcto de los días de la semana en los programas generados resultado de la traducción de código fuente Informix necesitamos saber el idioma en que esta configurado el entorno del usuario que los ejecuta sobre el gestor de bases de datos destino.

En el apartado: Ejemplo de funcion weekday, del Anexo I se muestra un ejemplo del trtamiento de esta función para cada gestor de baeses de datos. En este ejemplo se puede ver como se garantiza que el comportamiento final es el mismo que el que tiene el código original sobre Infomix.

NOTA:

Con estos cambios en la configuración de los usuarios, clientes o sesiones no estamos modificando en ningún momento la representación interna que el gestor haga de cada tipo de datos sino el formato en que este espera recibir y retorna los valores almacenados en el mismo.

En este momento ya se tiene claro que si se pretende que el código objeto generado pueda ser ejecutado sobre un gestor destino con la misma semántica se ha saber el idioma del usuario/sesión que ejecuta los programas. También se han proporcionado unas pequeñas nociones de que elementos de la configuración local se pueden ver afectados y como modificarlos.

TRATAMIENTO DE LAS FECHAS Las fechas son un elemento bastante complicado de tratar porque en su procesamiento intervienen bastantes elementos y cada uno de ellos con posible diferente configuración de formatos.

Page 217: IfxToJava2

217

RECONOCIMIENTO DE LAS FECHAS

El primer punto de problema es el reconocer los literales tipo fecha a la hora de procesar el código fuente ya que estos como literales no dejan de ser más que cadenas de caracteres. Para ello en el analizador léxico si se lee una cadena de caracteres se comprobará si contiene el valor de una fecha. La forma de hacerlo es basándose en el formato de fecha establecido en el entorno del cliente o el que tenga por defecto el gestor sino se fijo este. Si tenemos fijado DBDATE=DMY4/ y se lee una cadena como sigue: �20/12/2003� al tratar dicha cadena se verifica que casa con el formato establecido para las fechas y en tal caso se interpreta que es una fecha, en caso contrario será una cadena.

Para este procesamiento se utiliza la clase de Java simpleDateFormat que recibe como parámetro un formato de fecha (ver JavaDoc para mas información sobre los parámetros utilizados para la representación de los distintos formatos de fecha/hora) y luego permite utilizar alguno de sus métodos que permite verificar si realmente se cumple el formato de fecha definido, véase el siguiente ejemplo:

Leemos del código fuente el token: �10/12/2003�

SimpleDateFormat sdate = new SimpleDateFormat(�dd/mm/yyyy�); // correspondiente a: DBDATE=DMY4/

tokdat = sdate.parse(token,new ParsePosition(0));

Si retorna null o da una excepción: NullPointerException entonces no se trata de una fecha, en caso contrario si.

En el caso de que lo que estemos leyendo sea un literal fecha/hora el tratamiento es similar. Informix-SQL admite que en una cadena venga embebida un valor datetime siempre y cuando tenga el siguiente formato: �yyyy-MM-dd HH:mm:ss.ffffff�. El tratamiento es similar al utilizado para el reconocimiento de las constantes tipo fecha, véase el ejemplo:

Leerlo del código fuente el token: �2007-08-30 10:12:34.44�

SimpleDateFormat sdate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

tokdat = sdate.parse(token.substring(0,token.indexOf('.')),pos);

Si el resultado de esta operación es una excepción significa que la cadena que estamos comparando no casa con un una constante tipo fecha/hora en caso contrario si.

Si para definir el literal fecha/hora se utiliza la definición: datetime ( <valor> ) <rango> se reconoce el mismo en el análisis sintáctico.

Para reconocer valores tipo fecha con formato número se ha de hacer a través del análisis semántico. Este se ha de aplicar en las asignaciones, comparaciones, operaciones aritméticas, funciones y sentencias SQL.

En el caso de variables o campos e la base de datos se reconoce que son tipo fecha durante el análisis semántico, para ello se mantendrá una tabla de símbolos que guardará en las variables y sus tipos en el momento de su declaración y los campos asociado a su tabla en el momento de su creación. Si se hace referencia a un campo de una tabla que no se definió en el código fuente se realizará una consulta a la base de datos para determinar el tipo del mismo.

MOSTRAR VALORES

Un segundo caso se plantea cuando leemos un valor del gestor de bases de datos, por defecto se almacena en una variable tipo java.sql.Date la cual mantiene la fecha en formato JDBC que es el siguiente: 'yyyy-mm-dd'. Este formato puede no coincidir con el formato establecido en el entorno de usuario. Lo que se ha de hacer antes de mostrar el valor de la variable es convertirla al formato especificado en el entorno del usuario usando para ello la función: java.text.SimpleDateFormat, véase el siguiente ejemplo:

Recibimos la variable: java.sql.Date.fecha y el formato a mostrar es: dd/mm/yyyy el proceso a ejecutar será:

Page 218: IfxToJava2

218

java.text.SimpleDateFormat sdate = new java.text.SimpleDateFormat(�dd/MM/yyyy�);

System.out.println sdate.format(fecha);

INTERCAMBIO DE DATOS ENTRE JAVA Y EL GESTOR

En las sentencias de programa siempre habrá un intercambio de información entre el programa y la base de datos, este intercambio se hará a través de variables de programa, constantes y/o funciones SQL.

VARIABLES

Su uso más común es cuando en el código fuente Informix-4GL se define una variable de tipo DATE, se le asigna un valor y luego se utiliza en una sentencia SQL. El tipo DATE de Informix se pasará a un tipo java.sql.Date de API JDBC de Java con lo cual el formato del valor de tipo fecha que almacena dicha variable, 'yyyy-mm-dd', puede no casar con el que se haya definido para el gestor. Para entender esta necesidad de cambio de formato hay que tener un conocimiento profundo de las funciones JDBC utilizas para intercambiar información con los gestor de bases de datos. Estas funciones suelen recibir una cadena de caracteres con la sentencia SQL a ejecutar y en dicha cadena ya deben de ir interpretadas las variables tipo fecha de tal forma que al ser ejecutada sobre el gestor destino esta sea procesada de forma correcta, véase el ejemplo:

java.Sql.Date fecha = new Date .....

......

executeUpdate("insert into prueba1 values ( 'esto es una prueba' , �"+ fecha +"� , 12 ) ");

Si DBDATE esta fijado a DMY4/ al ejecutar esta sentencia nos dará el error siguiente:

-1204: [Informix][Informix ODBC Driver][Informix]Invalid year in date, en Sentencia:

insert into prueba1 values ( 'esto es una prueba' , '2006-08-05', 12 )

Como se ve el gestor ya recibe el valor de la variable tipo fecha y como no coincide con el formato que tiene establecido da error, para evitar este error habría que hacer un cambio de formato en tiempo de ejecución.

Para convertir las fechas que se pasan al gestor a través de las sentencias SQL hay varias formas: uno de ellos consiste en definir un método basado en la clase SimpleDateFormat que se ejecute en tiempo de ejecución y haga la conversión de formato y la otra consiste en pasarle este trabajo al driver JDBC, esta segunda forma depende del método que se utilice: executeQuery o prepareStatament, véanse los siguientes ejemplos:

Conversión de formato vía método definido por el �usuario� y lanzado en tiempo ejecución:

java.sql.Date fecha;

executeUpdate("insert into prueba1 values ( 'esto es una prueba' , �"+ convierteFecha(fecha) +"� , 12 ) ");

Evidentemente el método convierteFecha debe estar en una clase accesible en tiempo de ejecución y ha de estar preparado para convertir la fecha, que recibe como parámetro, al formato que espere el gestor de bases de datos sobre el cual se ejecuta la sentencia.

Si se utiliza la sentencia prepareSatatment el propio driver JDBC se encarga de hacer las conversiones de formato de fecha basándose para ello en el entorno del cliente. Ejemplo:

java.sql.Date fecha;

PreparedStatement x = conn.prepareStatement ("insert into tabla values(?)"); x.setDate(1, fecha); x.executeUpdate();

Una tercera posibilidad es la utilización de la sintaxis SQL92 embebida. JDBC soporta un

formato estándar ISO para los literales tipo fecha, hora y fecha/hora y para ello usa una

Page 219: IfxToJava2

219

cláusula de escape que le indica al driver que debe traducir el literal a la representación del gestor de bases de datos.

Una fecha se especifica en SQL JDBC mediante la sintaxis: {d `yyyy-mm-dd'}. En esta sintaxis, yyyy es el año, mm es el mes y dd es el día. El driver reemplazará la cláusula de escape por la representación propia equivalente del gestor de bases de datos. Por ejemplo, el driver reemplazaría {d �1999-02-28�} por �28-FEB-99� si este es el formato apropiado para la base subyacente.

Hay cláusulas de escape análogas para TIME y TIMESTAMP que son:

{t `hh:mm:ss'}

{ts `yyyy-mm-dd hh:mm:ss.f . . .'}

La parte fraccional de los segundos (.f . . .) del TIMESTAMP puede omitirse (es opcional).

Este sistema se aplica para el uso de variables de programa JAVA dentro de sentencias SQL ya que el formato de las variables tipo fecha de JAVA utilizan el formato ISO. La forma de utilizarlos se muestra en los siguientes ejemplos:

Sentencia original con tipo de datos fecha:

define fecha date

insert into prueba1 values (�esto es un prueba�, fecha, 12)

Sentencia generada:

java.sql.date fecha;

x.executeUpdate("insert into prueba1 values ( 'esto es una prueba' , { d �" + fecha + "� } , 12 ) ");

Sentencia original con tipo de datos fecha/hora:

define fechah datetime year to fraction

insert into prueba1 values (�esto es un prueba�, fechah, 12)

Sentencia generada:

java.sql.Timestamp fechah;

x.executeUpdate("insert into prueba1 values ( 'esto es una prueba' , { ts �" + fechah + "� } , 12 ) ");

Cualquiera de estas tres formas es posible para trabajar con variables de programa en sentencias SQL aunque son más trasparentes las dos ultimas debido a que se cede todo el trabajo al Driver JDBC.

A lo largo de los casos mostrados en el Anexo I se han plamado ejemplos del paso de fechas desde el lenguaje de programación al gestor de bases de datos.

CONSTANTES

Las constantes en el código fuente vienen en formato Informix y son reconocidas durante el análisis léxico o bien a través del análisis semántico. En el estudio realizado en el punto: expresiones de constantes, en el cual se tienen en consideración la configuración local, se indican las modificaciones que es preciso realizar para traducir código fuente a código objeto ejecutable sobre cada gestor de bases de datos. En la tabla siguiente se muestra un resumen:

Cte. Informix Cte. SqlServer Cte. Oracle Cte. DB2

Fecha: 37256 convert(datetime, 37256 ± cte ,103);

to_date( to_char(37256 ± cte, �99999999999�),�J�)

date(37256 ± cte)

Page 220: IfxToJava2

220

Fecha: �31/12/2006� �31/12/2006� ó

dateadd(dd,0, datediff(dd,0,� �31/12/2006�))

�31/12/2006� ó

to_date(to_char(�31/12/2006�,'dd/mm/yyyy'))

�31/12/2006� ó

date(�31/12/2006�)

FechaHora: datetime (2007-12-10 12:32:40)

year to fraction

Convert (datetime,'2007-12-10

11:21:30 ',121) )

timestamp '2007-12-10 11:21:30'

'2007-12-10 11:21:30'

Fecha-Hora: �2007-12-10 12:32:40�

Convert (datetime,'2007-12-10

11:21:30 ',121) )

timestamp '2007-12-10 11:21:30'

'2007-12-10 11:21:30'

Tabla 51: Uso de constantes tipo fecha en sentencias SQL

Para convertir una constante numérica que representa una fecha de Informix-4GL a otro gestor hay que tener claro: por un lado que fecha representa un valor numérico en el gestor original y en el resto de gestores y por otro lado que factor de corrección hay que aplicar al valor numérico que aparece en el código fuente para que se obtenga la misma fecha en el código objeto. La interpretación que hace cada gestor de una fecha en formato numérico es:

Informix. Considera el número de días desde el 31/12/1899.

SqlServer. Interpreta el número como los días que van desde el 01/01/1900.

Oracle. Como el número de días desde 1 de enero del 4712 antes de Cristo.

Y Db2 como el número de días desde el 01/01/0001.

En la siguiente tabla se muestran ejemplos de fechas y su representación numérica en cada uno de los gestores de bases de datos:

Fecha Informix SqlServer Oracle Db2

Día siguiente: 22/10/2007 39376 39375 2454396 732971

Día actual: 21/10/2007 39375 39374 2454395 732970

31/12/1899 0 -1 2415020 693595

01/01/1900 1 0 2415021 693596

02/01/1900 2 1 2415022 693597

03/01/1900 3 2 2415023 693598

Tabla 52: Valores numéricos asociados a una fecha en cada gestor

Observando esta tabla se puede obtener el factor de corrección que habrá que aplicar para dado una constante numérica, que representa una fecha en Informix, proporcionar el valor numérico que representa la misma fecha en el resto de gestores, este es:

SqlServer: -1

Oracle: 2415020

Y Db2: 693595

Denotar que esta misma traducción de las constantes numéricas se debe hace para las variables numéricas que se desea sean interpretadas como fechas.

Las constantes cadena que representan fechas son interpretadas directamente por el gestor destino, si el entorno tiene fijado el mismo formato de fecha, aunque es recomendable utilizar las funciones de conversión explicita de cadena a fecha que define cada gestor define, estas funciones

Page 221: IfxToJava2

221

se muestran en la tabla anterior: Tabla 51: Uso de constantes tipo fecha en sentencias SQL. Durante el proceso de traducción de código fuente a objeto en la parte referente a este tipo de constantes se han tenido que superar varios problemas:

Reconocerlas. Este tipo de constantes, basándonos en que Informix trabaja con un formato de fecha bien definido explícitamente (con DBDATE) o implícitamente (mm/dd/yyyy), son reconocidas en el análisis léxico.

Tratarlas. En todo punto donde Informix permite operar con una fecha en formato cadena se ha conseguido que el programa objeto resultante de la traducción también lo haga: asignación a variables de programa, paso como parámetro a funciones, operaciones aritméticas y relacionales, etc. Para esto fue preciso pasar las constantes tipo cadena a valores tipo fecha definidos por cada gestor ya que en caso contrario ciertas operaciones que Informix-SQL si admitía sobre este tipo de constantes algún otro gestor no. Como ejemplo Informix-SQL permite sumar un entero a una fecha aunque esta venga embebida en una cadena:

select �31/12/2001� + campo1 from prueba1;

Pero esta misma sentencia falla sobre otros gestores como por ejemplo: Oracle. La solución fue al reconocer la fecha embebida en una cadena realizar una conversión explicita:

select to_date(�31/12/2001�, �dd/mm/yyyy�) + campo1 from prueba1;

Superar problemas de definición de variables. Con esto se trata de hacer notar que Informix define las variables tipo DATE y DATETIME, la primera admite valores tipo fecha que especifican desde el año hasta el día, y la segunda admite valores tipo fecha/hora que soporta indicar desde el año hasta microsegundos. Al hacer el paso de código fuente Informix-SQL a los gestores Oracle y SqlServer el tipo DATE se asocia a: DATE Y SMALLDATETIME respectivamente, estos dos tipos de datos en el gestor destino permiten representar desde el año hasta el segundo lo cual supone un problema a la hora de operar con ellos, véanse los siguiente ejemplos:

insert into prueba1 values (1,3, today)

La traducción básica a Oracle y Sqlserver sería:

insert into prueba1 values (1,3, sysdate) y insert into prueba1 values (1,3,getdate())

Haciendo esto el valor en base de datos tendría mayor precisión para Oracle y Sqlserver que para Informix y evidentemente afectaría en el resultado de otras sentencias de programa como por ejemplo:

select count(*) from prueba1 where campo3 > �25/12/2007�

Si today = 25/12/2007 y el programa que contenga estas sentencias se ejecuta el resultado será diferente para el gestor de bases de datos Informix que para Oracle y Sqlserver ya que en estos últimos casos al considerar la parte hora de la fecha y para ellos campo3 si sería mayor que la fecha.

La solución ha este caso se dio despreciando la parte hora de estos valores, así en lugar de utilizar: sysdate se utilizará: to_date(to_char(sysdate,'dd/mm/yyyy�)) y para Sqlserver en lugar de utiliza: getdate() se utilizará: dateadd(dd,0, datediff(dd,0,getdate() )).

Las constantes tipo fecha/hora son reconocidas durante el análisis léxico, se deben transformar dentro del proceso de traducción a la forma en que son reconocidas por el gestor destino, siguiendo para ello la guía que se ve en la tabla anterior: Tabla 51: Uso de constantes tipo fecha en sentencias SQL.

En el Anexo I, apartadao: Ejemplo de manejo de constantes tipo fecha se muestra un caso completo del código fuente y objeto generado relativo al tratamiento de constantes tipo fecha para cada uno de los gestores de bases de datos.

FUNCIONES

El pasos de valores tipo fecha, fecha/hora retornados por funciones SQL ya se ha contemplado al estudiar las mismas (apartado: Funciones sql ) y la configuración local (ver: Configuración local )

Page 222: IfxToJava2

222

En los ejemplos indicados en el punto anterior se pueden ver casos en los que se estas funciones reciben como parámetros valores constantes tipo fecha.

CREACIÓN DE OBJETOS: PROPIETARIO Y ACCESO Todos los gestores de bases de datos proporcionan alguna forma de crear los usuarios que podrán acceder a la base de datos y de asignarles unos ciertos privilegios que determinen las acciones que pueden hacer sobre las mismas. Los dos tipos más habituales de usuarios que pueden acceder a la base de datos suelen ser: usuarios dados de alta de forma explícita en el gestor, o usuarios del sistema operativo en el cual esta instalado el mismo.

En esta sección no se pretende indicar como se crean, administran y se asignan privilegios a usuarios7 sino, partiendo de que los usuarios esta bien definidos y tienen los suficientes privilegios, determinar a que objetos tienen acceso y de que forma. Se ha de intentar garantizar que si un objeto creado, en el gestor de bases de datos Informix, por un usuario X el cual era visible para el resto de usuarios que utilizan la aplicación, y ahora dicha aplicación se intenta se ejecute sobre cualquier gestor de bases de datos se mantenga ese nivel de acceso a los objetos de forma transparente al usuario. Para garantizar esto se va ha hacer un estudio sobe todos los gestores determinando cuando se crea un objeto quien es el propietario del mismo y que implicaciones tiene esto a nivel de acceso y visibilidad para el resto de usuarios.

OBJETOS CREADOS EN INFORMIX

Informix-SQL no define usuarios del propio gestor de bases de datos sino que trabaja con los usuarios definidos el servidor en el cual esta instalado. El usuario administrador del gestor es: Informix y se crea durante el procedimiento de instalación del mismo como usuario del sistema operativo (esto puede variar en función de la plataforma: Windows, Unix).

Los objetos de la base de datos que se crean toman como propietario el usuario que esta conectado a la misma. Inicialmente el objeto puede ser accedido por el propietario y por el administrador de la base de datos. Para que el resto de usuarios tengan acceso se les ha de otorgar permisos a nivel de base de datos o tabla (ver sentencia grant/revoke).

Cuando se desea acceder a una objeto de la base de datos se puede acceder de dos formas: propietario.objeto o objeto el acceso será admitido por el gestor si el usuario que trata de ganar el acceso a la objeto tiene los suficientes privilegios. Cualquier usuario puede acceder al objeto sin indicar propietario si sobre el mismo se han otorgado permisos.

A diferencia de otros gestores no se permite que el mismo nombre de objeto este creado dos veces en una base de datos aunque el usuario que intenta crearlo sea diferente, ósea si el usuario X creó el objeto Y, otro usuario Z no podrá crear un objeto llamado Y, si lo intenta recibirá un error del gestor de base de datos

En el siguiente ejemplo se intentará dejar más claro el concepto, ejemplo: el usuario X crea el objeto O1. Para acceder al objeto O1 el usuario X y el resto, si tienen los suficientes privilegios, pude hacer: X.O1 ó O1.

OBJETOS CREADOS EN SQLSERVER

El gestor de bases de datos SqlServer permite trabajar con usuario de sistema operativo o definidos en el propio gestor. El usuario administrador de la base de datos es: sa.

Los objetos por defecto son creados con el propietario dbo, a no ser que el usuario actual tenga permisos para crearlos (db_creator) y no sea administrador del sistema. En tal caso los objetos tendrán como propietario el usuario conectado al gestor de bases de datos que lanza la sentencia de creación de los mismos.

7 Referirse a los manuales de Administración suministrados por los proveedores de bases de datos.

Page 223: IfxToJava2

223

El usuario quien crea objetos de la base de datos (tablas, índices, vistas, triggers, etc.) se llama propietario de objetos de la base de datos. Para que un usuario pueda crear objetos ha de tener permisos de �propietario de base de datos� o �administrador del sistema�.

Los usuarios creadores de objetos de la base de datos no tienen ningún identificador de usuario (login) o password especial. Cuando un creador de objetos crea uno obtiene los permisos sobre el mismo de forma implícita, pero debe de dar permisos de forma explícita a otros usuarios que necesiten acceder al objeto.

Cuando un usuario accede a un objeto creado por otro, el objeto debe de ser cualificado con el nombre del propietario del mismo; de otra forma no podríamos saber a que objeto se accede debido a que SqlServer admite la creación de varios objetos con el mismo nombre siempre y cuando hayan sido creado por diferentes propietarios. Sino se cualifica el objeto con el propietario cuando se hace referencia al mismo el servidor busca el objeto siguiendo el siguiente orden:

Dentro de los objetos creados por el usuario actual.

Dentro de los objetos creados por el usuario dbo.

Con el siguiente ejemplo tratará de afianzarse el concepto de propietario de un objeto en SqlServer, ejemplo:

Si el usuario X tiene permisos de �propietarios de base de datos� y no los tiene de �administrador del sistema� y crea la tabla T1. Todos los usuarios, excepto X, que quieran acceder a la tabla T1 deben de cualificarla con el nombre X: X.T1. Si el acceso a T1 no se cualifica con el nombre X el servidor buscará una tabla llamada T1 cuyo propietario sea el usuario actual y luego cuyo propietario sea dbo. Si ninguno de los dos usuarios: actual y dbo tienen una tabla llamada T1 se producirá un error, y si la tienen se estará trabajando con una tabla que no es la creada por el usuario X.

Si estamos logados en el servidor con el usuario X y creamos una tabla T1 dicha tabla se creará con el propietario X y este podrá acceder a ella con el nombre T1 ó X.T1.

Cuando el usuario tiene permisos de �administradores del sistema� y crea una tabla T1 esta se crea con el propietario dbo y el acceso a la misma, siguiendo la regla anterior, será como dbo.T1 o T1 aunque se este logrado como usuario X. Si en esta circunstancia se crea la tabla como X.T1 no se podrá acceder a ella a no ser que en todo caso se refiera a la misma como X.T1 ya que se intento acceder, sin indicar el propietario, como T1 se producirá un error debido a que el gestor ve al usuario como dbo al tener permisos de �administrador del sistema�.

OBJETOS CREADOS EN DB2

Db2 Trabaja también con usuarios de sistema operativo. El usuario administrador del gestor es: db2admin el cual se crea como usuario de sistema operativo en el momento de la instalación del mismo.

Los objetos creados en las bases de datos toman como propietario el usuario que los creo, que será el usuario que esta conectado a la base de datos en el momento de lanzar la sentencia de creación. En una base de datos puede haber dos objetos con el mismo nombre aunque creados por diferente usuario. El acceso a una tabla puede ser haciendo referencia a su nombre o a su propietario y después el nombre, sino se indica propietario intentará el acceso a la tabla que haya sido creada por él. En el caso de que se trate de acceder a una tabla, sin indicar propietario, que no haya sido creada por el usuario que trata de ganar el acceso se producirá un error.

A continuación se muestra un ejemplo aclaratorio: El usuario X crea el objeto O1. Todos los usuarios de la base de datos, con suficientes privilegios, pueden acceder al objeto con la notación: X.O1, el usuario X puede acceder como: O1 o X.O1, pero si cualquier otro usuario intenta acceder al objeto como: O1 o le dará un error ya que el objeto creado por X no es visible para él o accederá a otro objeto distinto creado por el usuario en cuestión.

OBJETOS CREADOS EN ORACLE

En Oracle se pueden definir los usuarios dentro la base de datos (gestión interna de usuarios) o como usuarios del sistema operativo. El usuario administrador de la base de datos es: system en sistemas unix o miembro de ORA_DBA en sistemas Windows.

Page 224: IfxToJava2

224

A nivel de acceso y visibilidad de objetos Oracle es similar a DB2.

CONCLUSIONES

Como paso previo se ha de tener en cuenta que el estudio realizado en los puntos anteriores para cada gestor puede tener leves variaciones en función de la versión del gestor de bases de datos con lo cual se debe de tomar con cierta precaución.

Lo que se ha de tratar es que el acceso a las tablas sea posible sin para ello tener que modificar el código que se genera. Dadas las características de Informix-SQL en el tratamiento del propietario de los objetos de la base de datos el problema se simplifica bastante.

Es importante que se definan bien los permisos de acceso a la base de datos y a los objetos de la misa (ver sentencia grant).

A continuación se presentan dos de los casos más probables que nos encontremos en los entornos donde esta la aplicación que queremos tratar y un posible tratamiento para el problema de acceso a los objetos de la base de datos:

Todos los objetos creados con el usuario X y todos los usuarios acceden a la aplicación con el usuario X.

Como la conexión se configurará para todos los gestores, indicando usuario y contraseña, se puede hacer que todos los usuarios clientes tengan el mismo fichero de configuración con lo cual todos accederán a la aplicación con el usuario X lo que implica que las tablas se crean siempre con dicho propietario y desde todos los clientes serán visibles todas las tablas.

El acceso a cualquier tabla indicando el propietario no plantea ningún problema. Para todos los gestores se encontrará los objetos definidos bien como: X.obj ó obj.

Todas las tablas creadas con el usuario X y todos los usuarios acceden a la aplicación con su usuario local.

Aquí al mantener cada usuario diferente se nos plantean problemas en todos los gestores de bases de datos, a excepción de Informix, ya que por muchos permisos que demos a nivel de base de datos o tablas un usuario Y no podrá ver las tablas creadas por otro usuario X a no ser que todos los accesos, en el código fuente, sean: X.tabla lo cual no es muy habitual. La solución a proponer depende de cada gestor.

SqlServer. En este gestor existe una solución sencilla que consiste en definir alias de usuarios, con esto se consigue que aunque los usuarios que se logan sean diferentes el gestor los vea todos como uno solo. De esta forma se elimina el problema de los propietarios de las tablas ya que siempre será el mismo y estamos en primera situación planteada.

Supongamos que el usuario X es el principal y que el usuario Y cualquier otro que trabaja con la aplicación, ambos usuarios deben de estar definidos a nivel de gestor de bases de datos, pero a nivel de la base de datos solo figurará el usuario X con privilegios de �creador de base de datos�. Entonces para que el/los usuario/s Y puedan trabajar con la base de datos se crea el alias como sigue:

sp_addalias @loginame = 'Y', @name_in_db = 'X'

A partir de este momento el usuario Y ya podrá trabajar con la base de datos e internamente el gestor lo trata como X lo que implica que solo habrá tablas creadas por X.

Oracle. Para este gestor lo que se puede hacer para que el usuario Y pueda ver las tablas creadas por el usuario X es crear sinónimos. Ejemplo:

Usuario X: create table prueba (uno smallint)

El usuario X podrá acceder a ella, pero el usuario Y no (a no ser que use la terminología (propietario.tabla)

Page 225: IfxToJava2

225

Si creamos un sinónimo como sigue: create synonym prueba for X.prueba desde el usuario Y (para lo cual a de tener los privilegios necesarios) a partir de este momento el usuario Y ya puede acceder a la tabla como si fuese el usuario X (sin usar el nombre de propietario)

Db2. La solución podría ser la misma que para el caso de Oracle.

Estas soluciones propuestas son validas partiendo de dos hechos bastante comunes: primero las tablas siempre las suele crear un único usuario bien administrador de la base de datos o de la aplicación y segundo todos los usuarios tienen los suficientes permisos a nivel de base de datos. Para otras situaciones habría que estudiar cada una con detenimiento.

CONFIGURACIÓN DE LA CONEXIÓN En la sección anterior: Configuración local, se indicó que podría ser preciso fijar algún valor de alguna variable de entorno del servidor para que los valores constantes sean entendidos por el gestor de bases de datos. La cuestión es: ¿como las utiliza nuestro programa en Java?, ósea como le indica al servidor que una cierta variable tiene un cierto valor y, aún más, como sabe que hay una variable de entorno que tiene que notificar al servidor.

La forma de hacer que el programa que se conecta a la base de datos tenga en cuenta las variables de entorno es fijando en el driver utilizado para establecer la conexión. En función del driver utilizado JDBC o ODBC (vía JDBC) y del proveedor del mismo la forma de establecerlas será diferente, con lo cual es necesario referirse a la información proporcionada por cada proveedor.

Para el caso de Informix, si la conexión se establece vía ODBC, es suficiente con fijar las variables de entorno vía línea de comandos aunque el proveedor proporciona entre el software cliente una herramienta que permite fijar estas variables de forma global sin tener que utilizar variables de entorno (setnet32).

En el caso de que la conexión se establezca vía JDBC las variables de entorno se deben establecer en la cadena de conexión. Ejemplo:

Cadena de conexión básica:

jdbc:Informix-SQLi://asg:1528/datos:informixserver=ol_asg

Añadir variable DBPATH:

jdbc:Informix-SQLi://asg:1528/datos:informixserver=ol_asg;DBDATE=DMY4/

Estas dos formas de fijar las variables de entorno a los Drivers proporcionados por el proveedor suelen ser las más estandarizadas (variables de entorno del sistema, variables a añadir a la cadena de conexión) con lo cual, para el caso de conexiones JDBC, será preciso proporcionar un sistema que nos permita añadir estas variables a la cadena de conexión sin necesidad de modificar los programas generados. La forma que se utiliza es a través de la utilización de un fichero de configuración en el cual se establecen todos los parámetros necesarios para la ejecución del programa de traducción de código y de los programas generados con él mismo (ver sección: ¡Error! No se encuentra el origen de la referencia.).

En el caso de SqlServer el usuario de conexión determina el idioma y con este todos los elementos de configuración local. El idioma se fija, como se indica en el punto creación de objetos: propietario y acceso, a nivel de usuario de bases de datos. Si la conexión se establece vía JDBC se entiende que es un usuario de bases de datos, pero si se establece vía ODBC se debe de indicar en el DSN que la conexión se realiza con un usuario de bases de datos.

En el caso de que se trabaje con Oracle estos valores se fijan en los parámetros de sesión: nls_session_parameters. Y en el caso de Db2 dependen de totalmente del idioma de la base de datos.

Page 226: IfxToJava2

226

PLANIFICACIÓN Y PRESUPUESTO A continuación se muestran la lista de tareas y diagrama gantt de las tareas que comprende la realización de este proyecto. Las fechas aunque no son realistas, ya que se considera que no hubo discontinuidad en la elaboración del mismo, la duración de las tareas si es objetiva.

Page 227: IfxToJava2

227

Figura 14: Lista te tareas del proyecto

Figura 15: Diagrama Gantt de tareas del proyecto

En la tabla que se muestra a continuación se plasma el coste del proyecto. Para su realización se han considerado dos costes:

Page 228: IfxToJava2

228

Un técnico cuyo coste hora se estima en 15 � hora.

Equipamiento que cubre equipo, software, costes variables, etc. que se estima en 1 � hora.

Nombre de tarea Costo total Coste Satisfecho Coste Restante

1 Definición del Proyecto 1.272,00 1.272,00 0

2 Recopilación de Información 3.840,00 3.840,00 0

4 Creación del Analizador léxico 1.280,00 1.280,00 0

5 Creación del Analizador sintáctico 15.360,00 15.360,00 0

6 Añadir semántica, tabla de símbolos y gestión de errores 3.840,00 3.840,00 0

7 Desarrollo módulos generadores de código 7.680,00 7.680,00 0

9 Estudio sentencias SQL de distintos gestores 7.680,00 7.680,00 0

10 Incorporación de sentencias al generador de código 5.120,00 5.120,00 0

11 Pruebas 3.840,00 3.840,00 0

12 Customización 11.520,00 0 11.520,00

Total 61.432,00 49.912,00 11.520,00

Tabla 53: Coste del proyecto

Page 229: IfxToJava2

229

MANUAL DE USUARIO El uso del traductor es muy sencillo, para su utilización es suficiente con lanzar la ejecución de un programa desde línea de comandos con una serie de parámetros y como resultado de la ejecución del mismo se genera el código objeto deseado. Aún así es preciso tener preparado el entorno y el software preciso instalado. También se proporcionan una serie de scripts que facilitan aún más el uso.

El manual de usuario se estructurará en las siguientes partes:

Requisitos hardware

Requisitos software

Configuración

Ejecución

REQUISITOS HARDWARE

El hardware mínimo necesario para ejecutar el traductor es:

Equipo P III 1 GHZ.

256 Mb. de memoria RAM.

10 GB. de disco duro.

Esta ha sido la plataforma mínima con la que se ha probado el traductor con resultados satisfactorios. Evidentemente y teniendo en cuenta que el/los gestores de bases de datos pueden estar instalados en la misma maquina se recomienda un sistema con mejores prestaciones.

REQUISITOS SOFTWARE

Los requisitos software han de abarcar varios ámbitos:

Sistema operativo

Gestores de bases de datos

JAVA y JDBC

REQUISITOS DE SISTEMA OPERATIVO

El sistema operativo sobre el cual se ejecuta el traductor, al estar este desarrollado en JAVA, tiene muy pocas limitaciones pudiendo ser:

Windows: 98, NT, Me, XP, W2000, w2003, o superior.

Linux: RedHat, Suse, Ubuntu, etc.

Unix: SCO, Solaris, HP-UX, etc.

La única limitación que ha de cumplir el sistema operativo es que soporte la versión JDK de JAVA requerida.

REQUISITOS DE LOS GESTORES DE BASES DE DATOS

Los gestores de bases de datos soportados y sus versiones mínimas requeridas son:

Informix visión 4.10 o superior.

SqlServer versión 2005 o superior.

Oracle versión 9i o superior.

Page 230: IfxToJava2

230

Db2 versión 8 o superior.

Cada gestor de bases de datos puede requerir alguna configuración especial, sobre todo en la parte correspondiente a usuarios y configuración local. Las configuraciones mínimas necesarias son comentadas en los puntos adecuados dentro del análisis de las sentencias SQL.

REQUISITOS DE JAVA Y API JDBC

En el equipo donde se ejecute el traductor ha de haber instalada una versión del JRE de JAVA versión 1.3 o superior. Se recomienda instalar el JDK para así poder probar los programas generados por el traductor.

En cuanto a los Drivers de conexión con la base de datos, al poder ser esta vía JDBC o ODBC sobre JDBC, podrán ser:

Si la conexión es vía ODBC: Instalar el cliente de conexión con la bases de datos. Este software viene con el propio software de instalación del gestor de bases de datos y su versión será acorde con el mismo.

Si la conexión es vía JDBC se requieran los Drivers estándares proporcionados por el proveedor del gestor de bases de datos en función de la versión del mismo.

CONFIGURACIÓN

Una vez instalados los componentes software necesarios se ha de configurar el entorno de trabajo y crear el fichero de configuración utilizado por el traductor.

ENTORNO DE TRABAJO

El entorno de trabajo ha de tener definidos los siguientes elementos:

Fijar variables de entorno:

CLASSPATH. Indicando en la misma el directorio base de instalación de JDK, directorio base de las API JDBC necesarias, directorio base las clases y packages pertenecientes al traductor, y directorio base de los fuentes generados (si se desean probar estos).

FUENTES. Indica el camino donde se encuentras los .class del traductor y los ficheros de configuración necesarios para su correcto funcionamiento.

PATH. Añadir al PATH el camino al directorio bin dentro del JDK de JAVA y el valor de la variable de entorno FUENTES.

Ubicar los programas fuentes. La ubicación de los programas fuente utilizados no tiene mayor importancia siempre y cuando las variables de entorno estén bien fijadas. El traductor entiende que los programas fuente están en el directorio desde el cual se laza la ejecución del mismo.

Ubicación de módulos objeto generados. Por defecto del traductor genera los programas objeto en el directorio desde el cual se lanza su ejecución.

FICHERO DE CONFIGURACIÓN

Para que se pueda lanzar la ejecución del traductor es preciso tener definidos una serie de parámetros. Estos parámetros proporcionan independencia al traductor respecto a la plataforma desde la cual se utilice, sobre que gestor de bases de datos vaya a trabajar, y además de fija una serie de valores que determinan su comportamiento.

Este fichero se llama: conexion.cfg, y consta de una serie de campos separados por una barra vertical (|). Aunque tiene una estructura prefijada no tienen porque tomar valor todos los campos definidos ya que estos dependerán del tipo de conexión a establecer y el gestor destino.

El fichero de configuración consta de los siguientes elementos:

Tipo de conexión a la base de datos. Indica, con un valor numérico, contra que tipo de base datos se ejecutará el programa. Estos valores numéricos se definen en el fichero de constantes SQL: GlobalSql.java y puede tomar los valores: NO_BD = -1

Page 231: IfxToJava2

231

BD_ODBC = 0 BD_Oracle = 1 BD_Informix = 2 BD_InformixOL = 3 BD_InformixSE = 9 BD_Sybase = 4 BD_Sqlserver = 5 BD_Db2 = 6 BD_Ingres = 7 BD_Mysql = 8

Destacar que si toma el valor 0 indicará que se trata de una conexión ODBC sobre JDBC.

DBdriver. Es el driver de conexión JDBC contra el gestor de base de datos, puede tomar los valores:

Para conexiones ODBC: sun.jdbc.odbc.JdbcOdbcDriver

Para Informix: com.informix.jdbc.IfxDriver

Para SqlServer: com.microsoft.sqlserver.jdbc.SQLServerDriver

Para Oracle: oracle.jdbc.driver.OracleDriver

Para Db2: com.ibm.db2.jcc.DB2Drive

Estos valores se obtienen de la información proporcionada por el proveedor del driver JDBC.

Driver. Contiene la URL de conexión con la base de datos, este valor dependerá de cada Driver JDBC. Para los Drivers considerados en este estudio los valores usados son:

Informix: jdbc:Informix-SQLi

SqlServer: jdbc:sqlserver:

Oracle: jdbc:oracle:thin:@

Db2: jdbc:db2:

Si se usa una Driver ODBC sobre JDBC en este campo se indica el nombre del controlador ODBC, ejemplos:

{INFORMIX 3.32 32 BIT}

{SQL Server}

{Oracle ODBC Driver}

{IBM DB2 ODBC DRIVER}

Origen ODBC. Este campo solo se rellenará si se ha especificado una conexión vía ODBC y contendrá el nombre del origen ODBC indicado en el origen de datos dentro del Administrador de orígenes de datos ODBC.

Path. Indica el camino completo de la base de datos. Solo se utiliza este campo en el caso de que estemos trabajando contra un gestor de bases de datos Informix-SE (Standard Engine).

Base de datos. Es el nombre de la base de datos.

Host: contiene la IP de la maquina donde esta instalado el gestor de bases de datos o el nombre en el caso de que este sea resuelto vía hosts, dns, etc.

Puerto: es el puerto en el que esta escuchando el servicio del servidor de bases de datos.

Informixserver. Campo que indica el nombre de la instancia del servidor. Solo se utiliza en gestores de bases de datos Informix.

Usuario. Indica el usuario de conexión a la base de datos.

Page 232: IfxToJava2

232

Password. Es la password del usuario de conexión a la base de datos.

Generación de código. Éste campo es utilizado, durante el proceso de traducción, para indicar para que gestor de bases de datos se esta haciendo la traducción de código fuente a código objeto. Puede tomar los mismos valores que el campo: Tipo de conexión a la base de datos, explicado anteriormente.

Idioma SGDB destino. Especifica el idioma del gestor de bases de datos destino, puede tomar los valores: E: español, U: americano (USA), A: ANSI, G: Alemán, I: Italiano. Este dato se utiliza, entre otras cosas, para calcular el número asociado al día de la semana y el formato de fecha en aquellas funciones de casting explicito en las que es preciso indicar el formato.

Esta definición del idioma no va en ningún caso sustituir las necesidades de configuración local que sea preciso realizar, simplemente son un complemento necesario para garantizar que ciertas operaciones se puedan llevar a cabo correctamente. Un caso claro de la utilidad de este campo es en el procesamiento de las constantes tipo fecha por los gestores de bases de datos SqlServer y Oracle, sino se indica en que formato viene la cadena a convertir pueden no ser bien interpretada. Ejemplos de cómo aplicarla:

to_date(�31/12/2007�,�dd/mm/yyyy�);

convert(datetime,�31/12/2007�,103);

Para el valor asociado al día de la semana solo se contemplan los idiomas español y americano.

Para el formato de fecha se contemplan todos los indicados. El formato de fecha en función de cada uno se muestra en la siguiente tabla:

Código de idioma Formato Informix Formato Oracle y Db2

Formato SqlServer

E DMY4/ dd/mm/yyyy dd/mm/yyyy 103

U MDY4/ mm/dd/yyyy mm/dd/yyyy 101

A Y4MD. yyyy.mm.dd yyyy.mm.dd 102

G DMY4. dd.mm.yyyy dd.mm.yyyy 104

I DMY4- dd-mm-yyyy dd-mm-yyyy 105

Tabla 54: Formato de fecha en función del idioma establecido

Utilizando esta variable de idioma también se fijará el formato de fecha que reconoce JAVA. Para JAVA el formato será igual que para Informix solo que sustituyendo el mm por MM (ver clase SimpleDateFormat).

Variables de entorno: Permite especificar variables de entorno que se fijarán en la cadena de conexión a la base de datos.

Generación de código. Indica si el código generado por el traductor proporcionará un interface grafico o no.

Seguidamente se muestras varios ejemplos de fichero de configuración. El primer caso es un fichero de configuración utilizado para generar código objeto que pueda ser lanzado contra el gestor de bases de datos Oracle, el tipo de conexión es JDBC, y no se genera un interface grafico.

1| #Tipo conexion a la base de datos oracle.jdbc.driver.OracleDriver| #DBdriver jdbc:oracle:thin:@| #Driver | #Origen ODBC (opcional) | #path (opcional) datos| #Base de datos asg| #Host 1521| #Puerto

Page 233: IfxToJava2

233

| #Informixserver (opcional) informix| #Usuario informix| #Passwd 1| #Generación de codigo E| #Idioma | #Vbles entorno 0| #Modo grafico o no

En este segundo caso el código objeto generado se podrá ejecutar sobre un gestor de bases de datos Informix, la conexión a establecer es tipo JDBC y se proporcionará un interface grafico estilo Windows.

0| #Tipo conexion a la base de datos sun.jdbc.odbc.JdbcOdbcDriver| #DBdriver {INFORMIX 3.32 32 BIT}| #Driver ifxdatos| #Origen ODBC (opcional) | #path (opcional) datos| #Base de datos asg| #Host 1528| #Puerto | #Informixserver (opcional) informix| #Usuario informix| #Passwd 2| #Generación de codigo E| #Idiosma | #Entorno 1| #Modo grafico o no

EJECUCIÓN DEL TRADUCTOR

EL traductor se ejecuta desde línea de comando, previa carga de las variables de entorno precisas. En función de si se está traduciendo un programa multimódulo o monomódulo se lanzará uno u otro programa.

TRADUCCIÓN DE PROGRAMAS MONOMÓDULO

Para traducir un programa monomódulo se ejecutará:

java ASGprog <fuente> [ traza ]

El fichero fuente puede ir con o sin extensión.

Si como segundo parámetro se pone el valor numérico 1 se generará un fichero de traza. Este fichero se llamará igual al nombre del fichero fuente con la extensión .log, y guardará todas las producciones por la que pasa el traductor en su proceso de traducción.

En caso de el programa fuente tenga algún error, lo cual no se debería de dar, el fichero de traza se generara de forma automática.

Como resultado de la ejecución del traductor se genera un fichero objeto que se llama igual que el fichero fuente pero con la extensión .java.

TRADUCCIÓN DE PROGRAMAS MONOMÓDULO

En el caso de que el programa conste de varios módulos será preciso disponer de un fichero makefile nombrado como: ASGmakefile en el cual se definan los módulos que constituyen el programa.

El fichero ASGmakefile se deduce fácilmente del fichero makefile original de Informix-4GL. En él se pueden definir más de un programa multimódulo y tendrá la siguiente estrucura:

NombreMóduloPrincipal = Módulo1.4gl Módulo2.4gl Módulo3.4gl �

Page 234: IfxToJava2

234

MóduloN.4gl exe: NombreMóduloPrincipal NombreOtroMóduloPrincipal = OtroMódulo1.4gl OtroMódulo2.4gl OtroMódulo3.4gl �

OtroMóduloN.4gl exe: NombreMóduloOtroPrincipal

Para lanzar la traducción de un programa mutimódulo se ejecuta:

java ASGmake NombreMóduloPrincipal [ parámetros opcionales ]

El fichero ASGmakefile del cual se obtiene la información para realizar el proceso de traducción debe de estar en el mismo directorio que los módulos que constituyen el programa multimódulo.

Como parámetros opcionales puede recibir los números:

1 Indica que se genere archivo de traza para cada módulo.

2 Fuerza la re-traducción de todos los módulos. El comportamiento normal del programa ASGmake es que si un el módulo objeto es más reciente que el módulo fuente éste no se re-traduce.

3 Indica se genere archivo de traza y se re-traduzcan todos los módulos del programa.

Como resultado de la ejecución del programa se generaran un módulo objeto por cada uno de los módulos fuente que constituyen el programa y en ocasiones un módulo adicional que contendrá variables globales accesibles desde cualquiera de los módulos objeto.

VERIFICACIÓN DE FUNCIONAMIENTO

La forma más sencilla para verificar el correcto comportamiento del traductor es ejecutar los programas generados. En ocasiones durante el proceso de traducción se lanzaran avisos que pueden sugerir revisar el código objeto generado.

Si se trata de un programa monomódulo la comprobación consistirá en:

Compilar el código objeto generado

javac codigo_objeto.java

Ejecutar el resultado de la compilación anterior

java codigo_objeto

Si se trata de un programa multimódulo la comprobación será la misma pero aplicando los dos pasos anteriores sobre el módulo principal ya que el JAVA compilará todos aquellos módulos que precise de forma automática.

Page 235: IfxToJava2

ANEXO I: FUENTES EJEMPLO SENTENCIA ALTER TABLE

CÓDIGO FUENTE INFORMIX-4GL: ALTERTABLE.4GL database datos main define yo,a,b,c smallint whenever error continue drop table tabla1 whenever error stop create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2), campo11 smallint , campo21 char(10) , campo31 decimal(4,2) ) alter index indice1 to not cluster alter table tabla1 modify(campo2 int unique ) alter table tabla1 modify(campo1 int not null unique constraint constr1, campo21 decimal(5,0), campo3 char ), add(campo4 int not null distinct constraint constr2, campo5 decimal(5,2) distinct constraint constr3 ), drop(campo11,campo21,campo31), add constraint unique (campo1,campo2,campo3), add constraint unique (campo1,campo2) constraint constr4 alter table tabla1 drop constraint (constr2,constr4) alter table informix.tabla1 modify(campo1 int) alter table "informix".tabla1 modify(campo1 int) end main

CÓDIGO OBEJTO: ALTERTABLE.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class altertable { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) , campo11 smallint , campo21 char(10) , campo31 decimal(4,2) ) "); ASGcondb.exeUpdate("alter table tabla1 modify ( campo2 integer unique ) "); ASGcondb.exeUpdate("alter table tabla1 modify ( campo1 integer not null unique constraint constr1 ) "); ASGcondb.exeUpdate("alter table tabla1 modify ( campo21 decimal(5,0) ) "); ASGcondb.exeUpdate("alter table tabla1 modify ( campo3 char(1) ) "); ASGcondb.exeUpdate("alter table tabla1 add ( campo4 integer not null unique constraint constr2 ) "); ASGcondb.exeUpdate("alter table tabla1 add ( campo5 decimal(5,2) unique constraint constr3 ) "); ASGcondb.exeUpdate("alter table tabla1 drop ( campo11 ) "); ASGcondb.exeUpdate("alter table tabla1 drop ( campo21 ) "); ASGcondb.exeUpdate("alter table tabla1 drop ( campo31 ) "); ASGcondb.exeUpdate("alter table tabla1 add constraint unique ( campo1 , campo2 , campo3 ) "); ASGcondb.exeUpdate("alter table tabla1 add constraint unique ( campo1 , campo2 ) constraint constr4 "); ASGcondb.exeUpdate("alter table tabla1 drop constraint ( constr2 ) "); ASGcondb.exeUpdate("alter table tabla1 drop constraint ( constr4 ) "); ASGcondb.exeUpdate("alter table tabla1 modify ( campo1 integer ) "); ASGcondb.exeUpdate("alter table tabla1 modify ( campo1 integer ) "); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class altertable { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos");

Page 236: IfxToJava2

236 ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) , campo11 smallint , campo21 char(10) , campo31 decimal(4,2) ) "); ASGcondb.exeUpdate("alter table tabla1 alter column campo2 integer "); ASGcondb.exeUpdate("alter table tabla1 add unique (campo2)"); ASGcondb.exeUpdate("alter table tabla1 alter column campo1 integer not null "); ASGcondb.exeUpdate("alter table tabla1 add constraint constr1 unique (campo1)"); ASGcondb.exeUpdate("alter table tabla1 alter column campo21 decimal(5,0) "); ASGcondb.exeUpdate("alter table tabla1 alter column campo3 char(1) "); ASGcondb.exeUpdate("alter table tabla1 add campo4 integer not null constraint constr2 unique "); ASGcondb.exeUpdate("alter table tabla1 add campo5 decimal(5,2) constraint constr3 unique "); ASGcondb.exeUpdate("alter table tabla1 drop column campo11 "); ASGcondb.exeUpdate("alter table tabla1 drop column campo21 "); ASGcondb.exeUpdate("alter table tabla1 drop column campo31 "); ASGcondb.exeUpdate("alter table tabla1 add unique ( campo1 , campo2 , campo3 ) "); ASGcondb.exeUpdate("alter table tabla1 add constraint constr4 unique ( campo1 , campo2 ) "); ASGcondb.exeUpdate("alter table tabla1 drop constraint constr2 "); ASGcondb.exeUpdate("alter table tabla1 drop constraint constr4 "); ASGcondb.exeUpdate("alter table tabla1 alter column campo1 integer "); ASGcondb.exeUpdate("alter table tabla1 alter column campo1 integer "); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class altertable { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) , campo11 smallint , campo21 char(10) , campo31 decimal(4,2) ) "); ASGcondb.exeUpdate("alter table tabla1 modify ( campo2 integer ) "); ASGcondb.exeUpdate("alter table tabla1 add unique (campo2)"); ASGcondb.exeUpdate("alter table tabla1 modify ( campo1 integer not null ) "); ASGcondb.exeUpdate("alter table tabla1 add constraint constr1 unique (campo1)"); ASGcondb.exeUpdate("alter table tabla1 modify ( campo21 decimal(5,0) ) "); ASGcondb.exeUpdate("alter table tabla1 modify ( campo3 char(1) ) "); ASGcondb.exeUpdate("alter table tabla1 add ( campo4 integer not null constraint constr2 unique ) "); ASGcondb.exeUpdate("alter table tabla1 add ( campo5 decimal(5,2) constraint constr3 unique ) "); ASGcondb.exeUpdate("alter table tabla1 drop ( campo11 ) "); ASGcondb.exeUpdate("alter table tabla1 drop ( campo21 ) "); ASGcondb.exeUpdate("alter table tabla1 drop ( campo31 ) "); ASGcondb.exeUpdate("alter table tabla1 add unique ( campo1 , campo2 , campo3 ) "); ASGcondb.exeUpdate("alter table tabla1 add constraint constr4 unique ( campo1 , campo2 ) "); ASGcondb.exeUpdate("alter table tabla1 drop constraint constr2 "); ASGcondb.exeUpdate("alter table tabla1 drop constraint constr4 "); ASGcondb.exeUpdate("alter table tabla1 modify ( campo1 integer ) "); ASGcondb.exeUpdate("alter table tabla1 modify ( campo1 integer ) "); } }

CODIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class altertable1 { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint not null , campo2 varchar(10) not null , campo3 decimal(4,2) not null , campo11 smallint ) "); ASGcondb.exeUpdate("alter table tabla1 alter column campo2 set data type varchar(12) "); ASGcondb.exeUpdate("alter table tabla1 add campo4 integer not null default constraint constr2 unique "); ASGcondb.exeUpdate("alter table tabla1 add campo5 decimal(5,2) constraint constr3 unique not null default "); ASGcondb.exeUpdate("alter table tabla1 add unique ( campo1 , campo3 ) "); ASGcondb.exeUpdate("alter table tabla1 add constraint constr4 unique ( campo1 , campo2 ) "); ASGcondb.exeUpdate("alter table tabla1 drop constraint constr2 "); ASGcondb.exeUpdate("alter table tabla1 drop constraint constr4 "); ASGcondb.exeUpdate("alter table tabla1 alter column campo2 set data type char(12) ");

Page 237: IfxToJava2

237 ASGcondb.exeUpdate("alter table tabla1 add unique (campo2)"); ASGcondb.exeUpdate("alter table tabla1 add unique ( campo11 ) "); } }

EJEMPLO SENTENCIAS CONEXIÓN/DESCONEXIÓN

CÓDIGO FUENTE INFORMIX-4GL: CONNECTDB.4GL database datos main whenever error continue drop table tabla1 whenever error stop create table tabla1 ( campo1 integer ) close database connect to datos2 whenever error continue drop table tabla1 whenever error stop create table tabla1 ( campo1 smallint, campo2 char(10), campo3 decimal(4,2) , campo4 decimal(2,0), campo5 int ) close database end main

CÓDIGO OBEJTO: CONNECTDB.JAVA import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class connectdb { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 integer ) "); ASGcondb.finConexionDB(); ASGcondb.iniConexionDB("datos2"); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) , campo4 decimal(2,0) , campo5 integer ) "); ASGcondb.finConexionDB(); } }

EJEMPLO SENTENCIAS DE TRATAMIENTO DE TRANSACCIONES

CÓDIGO FUENTE INFORMIX-4GL: TRANSAC.4GL database datos main define cuenta smallint whenever error continue drop table tabla1 whenever error stop create table tabla1 ( campo1 smallint, campo2 varchar(10) not null, campo3 char(50), campo4 decimal(5,2) ) select count(*) into cuenta from tabla1 message "Número de filas: ", cuenta begin work insert into tabla1 values(1,"1","2",2) commit work select count(*) into cuenta from tabla1

Page 238: IfxToJava2

238 message "Número de filas: ", cuenta begin work insert into tabla1 values(2,"2","3",3) rollback work select count(*) into cuenta from tabla1 message "Número de filas: ", cuenta begin work alter table tabla1 modify(campo2 varchar(12)) rollback work end main

CÓDIGO OBJETO: TRANSAC.JAVA import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class TRANSAC { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int cuenta ; cuenta = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 varchar(10) not null , campo3 char(50) , campo4 decimal(5,2) ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select count ( * ) from tabla1 "); try { ASG_r1.next(); cuenta = ASG_r1.getInt(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("Número de filas: " + cuenta ); ASGcondb.inicioTransac(); ASGcondb.exeUpdate("insert into tabla1 values ( 1 , '1' , '2' , 2 ) "); ASGcondb.finTransacOK(); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select count ( * ) from tabla1 "); try { ASG_r2.next(); cuenta = ASG_r2.getInt(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("Número de filas: " + cuenta ); ASGcondb.inicioTransac(); ASGcondb.exeUpdate("insert into tabla1 values ( 2 , '2' , '3' , 3 ) "); ASGcondb.finTransacKO(); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select count ( * ) from tabla1 "); try { ASG_r3.next(); cuenta = ASG_r3.getInt(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("Número de filas: " + cuenta ); ASGcondb.inicioTransac(); ASGcondb.exeUpdate("alter table tabla1 modify ( campo2 varchar(12) ) "); ASGcondb.finTransacKO(); } }

EJEMPLO SENTENCIA CREACION INDICE

CÓDIGO FUENTE INFORMIX-4GL: CREATEINDEX.4GL database datos main whenever error continue drop table tabla1 whenever error stop create table tabla1 ( campo1 smallint, campo2 char(10), campo3 decimal(4,2) ) create distinct cluster index indice1 on tabla1 (campo1 ASC, campo2 DESC) close database end main

Page 239: IfxToJava2

239

CÓDIGO OBJETO: CREATEINDEX.JAVA import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class createindex { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) ) "); ASGcondb.exeUpdate("create unique index indice1 on tabla1 ( campo1 asc , campo2 desc ) "); ASGcondb.finConexionDB(); } }

EJEMPLO SENTENCIA CREACION DE SINONIMOS

CÓDIGO FUENTE INFORMIX-4GL: SINONIMO.4GL main define uno,tres integer, dos char(10) whenever error continue drop table tabla1 whenever error stop create table tabla1 ( campo1 smallint, campo2 char(10), campo3 integer ) insert into tabla1 values (1,"1",1) create synonym sinonimo1 for tabla1 insert into sinonimo1 values (2,"2",2) select * into uno,dos,tres from sinonimo1 where campo1 = 1 message "valores fila 1: ",uno," ",dos," ",tres select * into uno,dos,tres from sinonimo1 where campo1 = 2 message "valores fila 2: ",uno," ",dos," ",tres drop table tabla1 select * into uno,dos,tres from sinonimo1 where campo1 = 2 message "valores fila 2: ",uno," ",dos," ",tres end main

CÓDIGO OBJETO: SINONIMO.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class sinonimo { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int uno , tres ; String dos ; uno = 0; tres = 0; dos = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 integer ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 1 , '1' , 1 ) "); ASGcondb.exeUpdate("create synonym sinonimo1 for tabla1 "); ASGcondb.exeUpdate("insert into sinonimo1 values ( 2 , '2' , 2 ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select * from sinonimo1 where campo1 = 1 "); try { ASG_r1.next(); uno = ASG_r1.getInt(1); dos = ASG_r1.getString(2); tres = ASG_r1.getInt(3); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close();

Page 240: IfxToJava2

240 System.out.println("valores fila 1: " + uno + " " + dos + " " + tres ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select * from sinonimo1 where campo1 = 2 "); try { ASG_r2.next(); uno = ASG_r2.getInt(1); dos = ASG_r2.getString(2); tres = ASG_r2.getInt(3); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("valores fila 2: " + uno + " " + dos + " " + tres ); ASGcondb.exeUpdate("drop table tabla1 "); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select * from sinonimo1 where campo1 = 2 "); try { ASG_r3.next(); uno = ASG_r3.getInt(1); dos = ASG_r3.getString(2); tres = ASG_r3.getInt(3); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("valores fila 2: " + uno + " " + dos + " " + tres ); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class sinonimo { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int uno , tres ; String dos ; uno = 0; tres = 0; dos = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 integer ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 1 , '1' , 1 ) "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop synonym sinonimo1"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create synonym sinonimo1 for tabla1 "); ASGcondb.exeUpdate("insert into sinonimo1 values ( 2 , '2' , 2 ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select * from sinonimo1 where campo1 = 1 "); try { ASG_r1.next(); uno = ASG_r1.getInt(1); dos = ASG_r1.getString(2); tres = ASG_r1.getInt(3); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("valores fila 1: " + uno + " " + dos + " " + tres ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select * from sinonimo1 where campo1 = 2 "); try { ASG_r2.next(); uno = ASG_r2.getInt(1); dos = ASG_r2.getString(2); tres = ASG_r2.getInt(3); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("valores fila 2: " + uno + " " + dos + " " + tres ); ASGcondb.exeUpdate("drop table tabla1 "); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select * from sinonimo1 where campo1 = 2 "); try { ASG_r3.next(); uno = ASG_r3.getInt(1); dos = ASG_r3.getString(2); tres = ASG_r3.getInt(3); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("valores fila 2: " + uno + " " + dos + " " + tres ); } }

CÓDIGO OBJETO ORACLE import java.sql.*;

Page 241: IfxToJava2

241import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class sinonimo { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int uno , tres ; String dos ; uno = 0; tres = 0; dos = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 integer ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 1 , '1' , 1 ) "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop public synonym sinonimo1"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create public synonym sinonimo1 for tabla1 "); ASGcondb.exeUpdate("insert into sinonimo1 values ( 2 , '2' , 2 ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select * from sinonimo1 where campo1 = 1 "); try { ASG_r1.next(); uno = ASG_r1.getInt(1); dos = ASG_r1.getString(2); tres = ASG_r1.getInt(3); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("valores fila 1: " + uno + " " + dos + " " + tres ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select * from sinonimo1 where campo1 = 2 "); try { ASG_r2.next(); uno = ASG_r2.getInt(1); dos = ASG_r2.getString(2); tres = ASG_r2.getInt(3); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("valores fila 2: " + uno + " " + dos + " " + tres ); ASGcondb.exeUpdate("drop table tabla1 cascade constraints"); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select * from sinonimo1 where campo1 = 2 "); try { ASG_r3.next(); uno = ASG_r3.getInt(1); dos = ASG_r3.getString(2); tres = ASG_r3.getInt(3); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("valores fila 2: " + uno + " " + dos + " " + tres ); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class sinonimo { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int uno , tres ; String dos ; uno = 0; tres = 0; dos = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 integer ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 1 , '1' , 1 ) "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop alias sinonimo1"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create synonym sinonimo1 for tabla1 "); ASGcondb.exeUpdate("insert into sinonimo1 values ( 2 , '2' , 2 ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select * from sinonimo1 where campo1 = 1 "); try { ASG_r1.next(); uno = ASG_r1.getInt(1); dos = ASG_r1.getString(2); tres = ASG_r1.getInt(3);

Page 242: IfxToJava2

242 } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("valores fila 1: " + uno + " " + dos + " " + tres ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select * from sinonimo1 where campo1 = 2 "); try { ASG_r2.next(); uno = ASG_r2.getInt(1); dos = ASG_r2.getString(2); tres = ASG_r2.getInt(3); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("valores fila 2: " + uno + " " + dos + " " + tres ); ASGcondb.exeUpdate("drop table tabla1 "); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select * from sinonimo1 where campo1 = 2 "); try { ASG_r3.next(); uno = ASG_r3.getInt(1); dos = ASG_r3.getString(2); tres = ASG_r3.getInt(3); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("valores fila 2: " + uno + " " + dos + " " + tres ); } }

EJEMPLO SENTENCIA CREACION DE TABLA

CÓDIGO FUENTE INFORMIX-4GL: CREATETABLE.4GL database datos main define yo,a,b,c smallint whenever error continue drop table tabla1 whenever error stop create table tabla1 ( campo1 smallint not null, campo2 char(10) unique, distinct (campo1) constraint constr1, campo3 decimal(4,2) distinct constraint constr2, unique (campo1,campo3) constraint constr3, campo4 decimal(2,0) not null, distinct (campo4), campo5 int, campo6 date, campo7 datetime hour to minute ) close database end main

CÓDIGO OBJETO: CREATETABLE.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class createtable { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint not null , campo2 char(10) unique , unique ( campo1 ) constraint constr1 , campo3 decimal(4,2) unique constraint constr2 , unique ( campo1 , campo3 ) constraint constr3 , campo4 decimal(2,0) not null , unique ( campo4 ) , campo5 integer , campo6 date , campo7 datetime hour to minute ) "); ASGcondb.finConexionDB(); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*;

Page 243: IfxToJava2

243import ASGutil.*; public class createtable { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint not null , campo2 char(10) unique , constraint constr1 unique ( campo1 ) , campo3 decimal(4,2) constraint constr2 unique , constraint constr3 unique ( campo1 , campo3 ) , campo4 decimal(2,0) not null , unique ( campo4 ) , campo5 integer , campo6 datetime , campo7 datetime ) "); ASGcondb.finConexionDB(); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class createtable { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint not null , campo2 char(10) unique , constraint constr1 unique ( campo1 ) , campo3 decimal(4,2) constraint constr2 unique , constraint constr3 unique ( campo1 , campo3 ) , campo4 decimal(2,0) not null , unique ( campo4 ) , campo5 integer , campo6 date , campo7 timestamp ) "); ASGcondb.finConexionDB(); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class createtable { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint not null , campo2 char(10) not null unique , constraint constr1 unique ( campo1 ) , campo3 decimal(4,2) constraint constr2 unique not null default , constraint constr3 unique ( campo1 , campo3 ) , campo4 decimal(2,0) not null , unique ( campo4 ) , campo5 integer , campo6 date , campo7 timestamp ) "); ASGcondb.finConexionDB(); } }

EJEMPLO SENTENCIAS CREACION TABLA TEMPORAL

CÓDIGO FUENTE INFORMIX-4GL: CREATETTABLE.4GL database datos main define yo,a,b,c smallint whenever error continue drop table tabla1 whenever error stop create temp table tabla1 ( campo1 smallint not null, campo2 char(10) unique, distinct (campo1) , campo3 decimal(4,2) distinct,

Page 244: IfxToJava2

244 unique (campo1,campo3), campo4 decimal(2,0) not null, distinct (campo4), campo5 int, campo6 date, campo7 datetime hour to minute ) close database end main

CÓDIGO OBJETO: CREATETTABLE.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class createttable { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create temp table tabla1 ( campo1 smallint not null , campo2 char(10) unique , unique ( campo1 ) , campo3 decimal(4,2) unique , unique ( campo1 , campo3 ) , campo4 decimal(2,0) not null , unique ( campo4 ) , campo5 integer , campo6 date , campo7 datetime hour to minute ) "); ASGcondb.finConexionDB(); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class createttable { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table #tabla1 ( campo1 smallint not null , campo2 char(10) unique , unique ( campo1 ) , campo3 decimal(4,2) unique , unique ( campo1 , campo3 ) , campo4 decimal(2,0) not null , unique ( campo4 ) , campo5 integer , campo6 datetime , campo7 datetime ) "); ASGcondb.finConexionDB(); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class createttable { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create global temporary table tabla1 ( campo1 smallint not null , campo2 char(10) unique , unique ( campo1 ) , campo3 decimal(4,2) unique , unique ( campo1 , campo3 ) , campo4 decimal(2,0) not null , unique ( campo4 ) , campo5 integer , campo6 date , campo7 timestamp ) "); ASGcondb.finConexionDB(); }

Page 245: IfxToJava2

245}

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class createttable { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("declare global temporary table tabla1 ( campo1 smallint not null , campo2 char(10) , campo3 decimal(4,2) , campo4 decimal(2,0) not null , campo5 integer , campo6 date , campo7 timestamp ) "); ASGcondb.finConexionDB(); } }

EJEMPLO SENTENCIA CREACION VISTA

CÓDIGO FUENTE INFORMIX-4GL: CREATEVIEW.4GL database datos main define uno,dos integer whenever error continue drop table tabla1 drop table tabla2 whenever error stop create table tabla1 ( campo1 smallint, campo2 char(10), campo3 decimal(4,2) ) create table tabla2 ( campo1 int, campo2 char(10), campo3 smallint ) insert into tabla1 values(1,"1",1.0) insert into tabla2 values(2,"2",2) create view vista1 (vcampo1,vcampo2) as select t.campo1, p.campo1 from tabla1 t, tabla2 p select * into uno,dos from vista1 message "campos de la vista: ",uno," ", dos end main

CÓDIGO OBJETO: CREATEVIEW.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class createview { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int uno , dos ; dos = 0; uno = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop table tabla2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) ) "); ASGcondb.exeUpdate("create table tabla2 ( campo1 integer , campo2 char(10) , campo3 smallint ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 1 , '1' , 1 ) "); ASGcondb.exeUpdate("insert into tabla2 values ( 2 , '2' , 2 ) "); ASGcondb.exeUpdate("create view vista1 ( vcampo1 , vcampo2 ) as select t.campo1 , p.campo1 from tabla1 t , tabla2 p "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select * from vista1 "); try { ASG_r1.next();

Page 246: IfxToJava2

246 uno = ASG_r1.getInt(1); dos = ASG_r1.getInt(2); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("campos de la vista: " + uno + " " + dos ); } }

CÓDIGO OBJETO SQLSERVER/DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class createview { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int uno , dos ; dos = 0; uno = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop table tabla2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) ) "); ASGcondb.exeUpdate("create table tabla2 ( campo1 integer , campo2 char(10) , campo3 smallint ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 1 , '1' , 1 ) "); ASGcondb.exeUpdate("insert into tabla2 values ( 2 , '2' , 2 ) "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create view vista1 ( vcampo1 , vcampo2 ) as select t.campo1 , p.campo1 from tabla1 t , tabla2 p "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select * from vista1 "); try { ASG_r1.next(); uno = ASG_r1.getInt(1); dos = ASG_r1.getInt(2); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("campos de la vista: " + uno + " " + dos ); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class createview { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int uno , dos ; dos = 0; uno = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 cascade constraints"); ASGcondb.exeUpdate("drop table tabla2 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) ) "); ASGcondb.exeUpdate("create table tabla2 ( campo1 integer , campo2 char(10) , campo3 smallint ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 1 , '1' , 1 ) "); ASGcondb.exeUpdate("insert into tabla2 values ( 2 , '2' , 2 ) "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create view vista1 ( vcampo1 , vcampo2 ) as select t.campo1 , p.campo1 from tabla1 t , tabla2 p "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select * from vista1 "); try { ASG_r1.next(); uno = ASG_r1.getInt(1); dos = ASG_r1.getInt(2); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("campos de la vista: " + uno + " " + dos ); } }

Page 247: IfxToJava2

247

EJEMPLO SENTENCIA DELETE

CÓDIGO FUENTE INFORMIX-4GL: DELETE.4GL database datos main define uno integer whenever error stop drop table tabla1 whenever error continue create table tabla1 ( campo1 smallint, campo2 smallint ) insert into tabla1 values (1,1) insert into tabla1 values (2,2) insert into tabla1 values (3,3) insert into tabla1 values (4,4) create view vista1 (vcampo1,vcampo2) as select * from tabla1 create synonym sinonimo1 for tabla1 select count(*) into uno from vista1 message "Número de filas: ", uno delete from vista1 where vcampo1 = 1 select count(*) into uno from sinonimo1 message "Número de filas: ", uno delete from sinonimo1 where campo1 = 2 select count(*) into uno from tabla1 message "Número de filas: ", uno delete from sinonimo1 where campo1 = 3 select count(*) into uno from tabla1 message "Número de filas: ", uno end main

CÓDIGO OBJETO: DELETE.JAVA

Aunque los códigos objeto, del ejemplo, no son iguales en función del gestor de bases de datos destino la diferencia viene marcada por sentencias adicionales a la que se trata de ejemplificar. import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class delete { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int uno ; uno = 0; ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("drop table tabla1 cascade constraints"); ASGcondb.activaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 smallint ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 1 , 1 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 2 , 2 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 3 , 3 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 4 , 4 ) "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create view vista1 ( vcampo1 , vcampo2 ) as select * from tabla1 "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop public synonym sinonimo1"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create public synonym sinonimo1 for tabla1 "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select count ( * ) from vista1 "); try { ASG_r1.next(); uno = ASG_r1.getInt(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("Número de filas: " + uno ); ASGcondb.exeUpdate("delete from vista1 where vcampo1 = 1 "); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select count ( * ) from sinonimo1 "); try { ASG_r2.next(); uno = ASG_r2.getInt(1); }

Page 248: IfxToJava2

248 catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("Número de filas: " + uno ); ASGcondb.exeUpdate("delete from sinonimo1 where campo1 = 2 "); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select count ( * ) from tabla1 "); try { ASG_r3.next(); uno = ASG_r3.getInt(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("Número de filas: " + uno ); ASGcondb.exeUpdate("delete from sinonimo1 where campo1 = 3 "); Statement ASG_st4 = ASGcondb.retCon().createStatement(); ResultSet ASG_r4 = ASG_st4.executeQuery("select count ( * ) from tabla1 "); try { ASG_r4.next(); uno = ASG_r4.getInt(1); } catch (SQLException e) {} ASG_r4.close(); ASG_st4.close(); System.out.println("Número de filas: " + uno ); } }

EJEMPLO SENTENCIA DROP INDEX

CÓDIGO FUENTE INFORMIX-4GL: DROPINDEX.4GL database datos main whenever error continue drop table tabla1 drop table tabla2 whenever error stop create table tabla1 ( campo1 smallint, campo2 char(10), campo3 decimal(4,2) ) create table tabla2 ( campo1 smallint ) create distinct cluster index indice1 on tabla1 (campo1 ASC, campo2 DESC) create index indice2 on tabla1 (campo1) drop index indice2 close database end main

CÓDIGO OBJETO: DROPINDEX.JAVA

CÓDIGO OBJETO INFORMIX/ORACLE/DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class dropindex { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop table tabla2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) ) "); ASGcondb.exeUpdate("create table tabla2 ( campo1 smallint ) "); ASGcondb.exeUpdate("create unique index indice1 on tabla1 ( campo1 asc , campo2 desc ) "); ASGcondb.exeUpdate("create index indice2 on tabla1 ( campo1 asc ) "); ASGcondb.exeUpdate("drop index indice2 "); ASGcondb.finConexionDB(); } }

CODIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class dropindex {

Page 249: IfxToJava2

249 private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop table tabla2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) ) "); ASGcondb.exeUpdate("create table tabla2 ( campo1 smallint ) "); ASGcondb.exeUpdate("create unique index indice1 on tabla1 ( campo1 asc , campo2 desc ) "); ASGcondb.exeUpdate("create index indice2 on tabla1 ( campo1 asc ) "); ASGcondb.exeUpdate("drop index "+ASGfaux.tablaindice(ASGcondb,"indice2")+""); ASGcondb.finConexionDB(); } }

EJEMPLO SENTENCIA DROP OBJETO

CÓDIGO FUENTE INFORMIX-4GL: DROPALL.4GL database datos main define yo,a,b,c smallint whenever error continue drop table tabla1 drop table tabla2 whenever error stop create table tabla1 ( campo1 smallint not null, campo2 char(10) unique, distinct (campo1) constraint constr1, #campo3 decimal(4,2) not null distinct constraint constr2, campo3 decimal(4,2) distinct constraint constr2, unique (campo1,campo3) constraint constr3, campo4 decimal(2,0) not null, distinct (campo4), campo5 int, campo6 date, campo7 datetime hour to minute ) create synonym sinonimo1 for tabla1 create view vista1 as select * from tabla1 drop synonym sinonimo1 drop table tabla1 create table tabla2 (campo1 smallint) create synonym sinonimo1 for tabla2 create view vista1 as select * from tabla2 drop view vista1 close database end main

CÓDIGO OBJETO: DROPALL.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class dropall { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop table tabla2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint not null , campo2 char(10) unique , unique ( campo1 ) constraint constr1 , campo3 decimal(4,2) unique constraint constr2 , unique ( campo1 , campo3 ) constraint constr3 , campo4 decimal(2,0) not null , unique ( campo4 ) , campo5 integer , campo6 date , campo7 datetime hour to minute ) "); ASGcondb.exeUpdate("create synonym sinonimo1 for tabla1 "); ASGcondb.exeUpdate("create view vista1 as select * from tabla1 "); ASGcondb.exeUpdate("drop synonym sinonimo1 "); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("create table tabla2 ( campo1 smallint ) "); ASGcondb.exeUpdate("create synonym sinonimo1 for tabla2 "); ASGcondb.exeUpdate("create view vista1 as select * from tabla2 "); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.finConexionDB(); }

Page 250: IfxToJava2

250}

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class dropall { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop table tabla2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint not null , campo2 char(10) unique , constraint constr1 unique ( campo1 ) , campo3 decimal(4,2) constraint constr2 unique , constraint constr3 unique ( campo1 , campo3 ) , campo4 decimal(2,0) not null , unique ( campo4 ) , campo5 integer , campo6 datetime , campo7 datetime ) "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop synonym sinonimo1"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create synonym sinonimo1 for tabla1 "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create view vista1 as select * from tabla1 "); ASGcondb.exeUpdate("drop synonym sinonimo1 "); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("create table tabla2 ( campo1 smallint ) "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop synonym sinonimo1"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create synonym sinonimo1 for tabla2 "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create view vista1 as select * from tabla2 "); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.finConexionDB(); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class dropall { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 cascade constraints"); ASGcondb.exeUpdate("drop table tabla2 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint not null , campo2 char(10) unique , constraint constr1 unique ( campo1 ) , campo3 decimal(4,2) constraint constr2 unique , constraint constr3 unique ( campo1 , campo3 ) , campo4 decimal(2,0) not null , unique ( campo4 ) , campo5 integer , campo6 date , campo7 timestamp ) "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop public synonym sinonimo1"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create public synonym sinonimo1 for tabla1 "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create view vista1 as select * from tabla1 "); ASGcondb.exeUpdate("drop public synonym sinonimo1 "); ASGcondb.exeUpdate("drop table tabla1 cascade constraints"); ASGcondb.exeUpdate("create table tabla2 ( campo1 smallint ) "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop public synonym sinonimo1"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create public synonym sinonimo1 for tabla2 "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create view vista1 as select * from tabla2 "); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.finConexionDB(); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*;

Page 251: IfxToJava2

251import ASGutil.*; public class dropall { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop table tabla2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint not null , campo2 char(10) not null unique , constraint constr1 unique ( campo1 ) , campo3 decimal(4,2) constraint constr2 unique not null default , constraint constr3 unique ( campo1 , campo3 ) , campo4 decimal(2,0) not null , unique ( campo4 ) , campo5 integer , campo6 date , campo7 timestamp ) "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop alias sinonimo1"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create synonym sinonimo1 for tabla1 "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create view vista1 as select * from tabla1 "); ASGcondb.exeUpdate("drop alias sinonimo1 "); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("create table tabla2 ( campo1 smallint ) "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop alias sinonimo1"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create synonym sinonimo1 for tabla2 "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create view vista1 as select * from tabla2 "); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.finConexionDB(); } }

EJEMPLO SENTENCIA GRANT

CÓDIGO FUENTE INFORMIX-4GL: GRANT.4GL main grant dba to public grant insert on tabla1 to public end main

CÓDIGO OBJETO: GRANT.JAVA import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class grant { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGcondb.exeUpdate("grant insert on tabla1 to public "); } }

EJEMPLO SENTENCIA INSERT

CÓDIGO FUENTE INFORMIX-4GL: INSERT.4GL database datos main whenever error continue drop table tabla1 drop table tabla2 whenever error stop create table tabla1 ( campo1 smallint, campo2 decimal(2,0), campo3 char(10) ) create table tabla2 ( campo1 smallint, campo2 decimal(2,0) ) insert into tabla1 values (1,1,"1"); insert into tabla1 values (2,2,"2"); create view vista1 (campo1,campo2,campo3) as select r.campo1,r.campo2, 3 from tabla1 r insert into tabla2 select campo3, campo2 from vista1

Page 252: IfxToJava2

252 end main

CÓDIGO OBJETO: INSERT.JAVA import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class insert { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 cascade constraints"); ASGcondb.exeUpdate("drop table tabla2 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 decimal(2,0) , campo3 char(10) ) "); ASGcondb.exeUpdate("create table tabla2 ( campo1 smallint , campo2 decimal(2,0) ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 1 , 1 , '1' ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 2 , 2 , '2' ) "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create view vista1 ( campo1 , campo2 , campo3 ) as select r.campo1 , r.campo2 , 3 from tabla1 r "); ASGcondb.exeUpdate("insert into tabla2 select campo3 , campo2 from vista1 "); } }

EJEMPLO SENTENCIA LOAD/UNLOAD

CÓDIGO FUENTE INFORMIX-4GL: LOADUNLOAD.4GL database datos main define fichero char(50) whenever error continue drop table tabla2 whenever error stop create table tabla2 ( campo1 decimal(5,2), campo2 char(5), campo3 date ) create index i1_tabla2 on tabla2(campo1) insert into tabla2 values(1,"yo","31/12/2003") let fichero = "|" load from "insert1.unl" delimiter fichero insert into tabla2 let fichero = "insert2.unl" load from fichero delimiter ";" insert into tabla2 let fichero = "insert into tabla2(pp,manolo)" load from "insert1.unl" fichero unload to "insert4.unl" select * from tabla2 end main

CÓDIGO OBJETO: LOADUNLOAD.JAVA import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class loadunload { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String fichero ; fichero = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla2 ( campo1 decimal(5,2) , campo2 char(5) , campo3 datetime ) "); ASGcondb.exeUpdate("create index i1_tabla2 on tabla2 ( campo1 asc ) "); ASGcondb.exeUpdate("insert into tabla2 values ( 1 , 'yo' , convert(datetime,'31/12/2003',103) ) "); fichero = "|" ; ASGcondb.load("insert1.unl" ,fichero ,"insert into tabla2 "); fichero = "insert2.unl" ; ASGcondb.load(fichero ,";" ,"insert into tabla2 "); fichero = "insert into tabla2" ; ASGcondb.load("insert1.unl" ,"|" ,fichero ); ASGcondb.unload("insert4.unl" ,"|" ,"select * from tabla2 "); } }

Page 253: IfxToJava2

253

EJEMPLO SENTENCIA LOCK/UNLOCK

CÓDIGO FUENTE INFORMIX-4GL: LOCK.4GL database datos main whenever error continue drop table tabla1 whenever error stop create table tabla1 ( campo1 smallint, campo2 decimal(2,0), campo3 char(10) ) insert into tabla1 values (1,1,"uno"); insert into tabla1 values (2,2,"dos"); lock table tabla1 in exclusive mode insert into tabla1 values (3,3,"tres"); update tabla1 set campo2 = 4 where campo1 = 1 unlock table tabla1 end main

CÓDIGO OBJETO: LOCK.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class lock { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 decimal(2,0) , campo3 char(10) ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 1 , 1 , 'uno' ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 2 , 2 , 'dos' ) "); ASGcondb.inicioTransac(); ASGcondb.exeUpdate("lock table tabla1 in exclusive mode "); ASGcondb.exeUpdate("insert into tabla1 values ( 3 , 3 , 'tres' ) "); ASGcondb.exeUpdate("update tabla1 set campo2 = 4 where campo1 = 1 "); ASGcondb.exeUpdate("unlock table tabla1 "); ASGcondb.finTransacOK(); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class lock { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 decimal(2,0) , campo3 char(10) ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 1 , 1 , 'uno' ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 2 , 2 , 'dos' ) "); ASGcondb.inicioTransac(); ASGcondb.exeUpdate("insert into tabla1 values ( 3 , 3 , 'tres' ) "); ASGcondb.exeUpdate("update tabla1 set campo2 = 4 where campo1 = 1 "); ASGcondb.finTransacOK(); } }

CÓDIGO OBJETO ORACLE/DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class lock { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac();

Page 254: IfxToJava2

254 ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 decimal(2,0) , campo3 char(10) ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 1 , 1 , 'uno' ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 2 , 2 , 'dos' ) "); ASGcondb.inicioTransac(); ASGcondb.exeUpdate("lock table tabla1 in exclusive mode "); ASGcondb.exeUpdate("insert into tabla1 values ( 3 , 3 , 'tres' ) "); ASGcondb.exeUpdate("update tabla1 set campo2 = 4 where campo1 = 1 "); ASGcondb.finTransacOK(); } }

EJEMPLO SENTENCIA RENAME COLUMN

CÓDIGO FUENTE INFORMIX-4GL: RENAMECOLUMN.4GL database datos main define yo,a,b,c smallint whenever error continue drop table tabla1 whenever error stop create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2), campo11 smallint , campo21 char(10) , campo31 decimal(4,2) ) rename column tabla1.campo31 TO campo22 end main

CÓDIGO OBJETO: RENAMECOLUMN.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class renamecolumn { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) , campo11 smallint , campo21 char(10) , campo31 decimal(4,2) ) "); ASGcondb.exeUpdate("rename column tabla1.campo31 to campo22"); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class renamecolumn { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) , campo11 smallint , campo21 char(10) , campo31 decimal(4,2) ) "); ASGcondb.exeUpdate("sp_rename 'tabla1.campo31', 'campo22', 'COLUMN'"); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*;

Page 255: IfxToJava2

255import ASGdbutil.*; import ASGutil.*; public class renamecolumn { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) , campo11 smallint , campo21 char(10) , campo31 decimal(4,2) ) "); ASGcondb.exeUpdate("alter table tabla1 rename column campo31 to campo22"); } }

EJEMPLO SENTENCIA RENAME TABLA

CÓDIGO FUENTE INFORMIX-4GL: RENAMETABLE.4GL database datos main define yo,a,b,c smallint whenever error continue drop table tabla1 drop table tabla11 whenever error stop create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2), campo11 smallint , campo21 char(10) , campo31 decimal(4,2) ) rename table tabla1 TO tabla11 end main

CÓDIGO OBJETO: RENAMETABLE.JAVA

CÓDIGO OBJETO INFORMIX/ORACLE/DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class renametable { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop table tabla11 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) , campo11 smallint , campo21 char(10) , campo31 decimal(4,2) ) "); ASGcondb.exeUpdate("rename table tabla1 to tabla11"); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class renametable { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int yo , a , b , c ; c = 0; a = 0; yo = 0; b = 0;

Page 256: IfxToJava2

256 ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop table tabla11 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(4,2) , campo11 smallint , campo21 char(10) , campo31 decimal(4,2) ) "); ASGcondb.exeUpdate("sp_rename 'tabla1', 'tabla11'"); } }

EJEMPLO SENTENCIA PREPARE/EXECUTE � PREPARE/DECLARE

CÓDIGO FUENTE INFORMIX-4GL: PREPAREDECLARE.4GL database datos define vcuatro smallint main define vuno, vuno1,vuno2 smallint, vdos decimal (10,3), vtres,vcuatro char(20), cad char(200) whenever error continue drop table tabla1 drop view vista1 whenever error stop create table tabla1 ( campo1 smallint, campo2 char(10), campo3 decimal(2,0) ) prepare s1 from "insert into tabla1 values (1,'1',1)" execute s1 let vtres = "tabla1" let cad = "create view vista1 (vcamp1,vcamp2,vcamp3) as ", "select * from ",vtres message cad prepare s2 from cad execute s2 let vuno = 2 let vdos = 2.0 prepare s3 from "insert into tabla1 values (?,?,?)" execute s3 using vuno,vtres,vdos prepare s4 from "select count(*) from tabla1" declare c4 cursor for s4 open c4 fetch c4 into vuno close c4 message vuno declare c5 cursor for select max(campo1) from tabla1 open c5 fetch c5 into vuno close c5 message vuno end main

CÓDIGO OBJETO: PREPAREEXECUTE.JAVA

CÓDIGO OBJETO INFORMIX/SQLSERVER/ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class preparedeclare { static int vcuatro ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int vuno , vuno1 , vuno2 ; double vdos ; String vtres , vcuatro ; String cad ; vuno = 0; vdos = 0.0; vuno1 = 0; vtres = ""; vuno2 = 0; vcuatro = ""; cad = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(2,0) ) "); PreparedStatement ASG_sp_s1 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (1,'1',1)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);

Page 257: IfxToJava2

257 ASG_sp_s1.executeUpdate(); ASG_sp_s1.close(); vtres = "tabla1" ; cad = "create view vista1 (vcamp1,vcamp2,vcamp3) as " + "select * from " + vtres ; System.out.println(cad ); PreparedStatement ASG_sp_s2 = ASGcondb.retCon().prepareStatement(cad ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s2.executeUpdate(); ASG_sp_s2.close(); vuno = 2 ; vdos = 2 ; PreparedStatement ASG_sp_s3 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (?,?,?)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s3.setInt(1,vuno); ASG_sp_s3.setString(2,vtres); ASG_sp_s3.setDouble(3,vdos); ASG_sp_s3.executeUpdate(); ASG_sp_s3.close(); PreparedStatement ASG_sp_s4 = ASGcondb.retCon().prepareStatement("select count(*) from tabla1" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c4 = ASG_sp_s4.executeQuery(); try { ASG_rsp_c4.next(); vuno = ASG_rsp_c4.getInt(1); } catch (SQLException e) {} ASG_rsp_c4.close(); ASG_sp_s4.close(); System.out.println(vuno ); Statement ASG_sp_c5 = ASGcondb.retCon().createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c5 = ASG_sp_c5.executeQuery("select max ( campo1 ) from tabla1 "); try { ASG_rsp_c5.next(); vuno = ASG_rsp_c5.getInt(1); } catch (SQLException e) {} ASG_rsp_c5.close(); ASG_sp_c5.close(); System.out.println(vuno ); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class preparedeclare { static int vcuatro ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int vuno , vuno1 , vuno2 ; double vdos ; String vtres , vcuatro ; String cad ; vuno = 0; vdos = 0.0; vuno1 = 0; vtres = ""; vuno2 = 0; vcuatro = ""; cad = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(2,0) ) "); PreparedStatement ASG_sp_s1 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (1,'1',1)" ,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s1.executeUpdate(); ASG_sp_s1.close(); vtres = "tabla1" ; cad = "create view vista1 (vcamp1,vcamp2,vcamp3) as " + "select * from " + vtres ; System.out.println(cad ); PreparedStatement ASG_sp_s2 = ASGcondb.retCon().prepareStatement(cad ,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s2.executeUpdate(); ASG_sp_s2.close(); vuno = 2 ; vdos = 2 ; PreparedStatement ASG_sp_s3 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (?,?,?)" ,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s3.setInt(1,vuno); ASG_sp_s3.setString(2,vtres); ASG_sp_s3.setDouble(3,vdos); ASG_sp_s3.executeUpdate(); ASG_sp_s3.close(); PreparedStatement ASG_sp_s4 = ASGcondb.retCon().prepareStatement("select count(*) from tabla1" ,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c4 = ASG_sp_s4.executeQuery(); try { ASG_rsp_c4.next(); vuno = ASG_rsp_c4.getInt(1); } catch (SQLException e) {} ASG_rsp_c4.close(); ASG_sp_s4.close(); System.out.println(vuno );

Page 258: IfxToJava2

258 Statement ASG_sp_c5 = ASGcondb.retCon().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c5 = ASG_sp_c5.executeQuery("select max ( campo1 ) from tabla1 "); try { ASG_rsp_c5.next(); vuno = ASG_rsp_c5.getInt(1); } catch (SQLException e) {} ASG_rsp_c5.close(); ASG_sp_c5.close(); System.out.println(vuno ); } }

EJEMPLO SENTENCIA DECLAREFORUPDATE

CÓDIGO FUENTE INFORMIX-4GL: DECLAREFORUPDATE.4GL database datos define vcuatro smallint main define vuno, vuno1,vuno2 smallint, vdos decimal (10,3), vtres,vcuatro char(20), cad char(200) whenever error continue drop table tabla1 drop view vista1 whenever error stop create table tabla1 ( campo1 smallint, campo2 char(10), campo3 decimal(2,0) ) prepare s1 from "insert into tabla1 values (1,'1',1)" execute s1 let vtres = "tabla1" let cad = "create view vista1 (vcamp1,vcamp2,vcamp3) as ", "select * from ",vtres message cad prepare s2 from cad execute s2 let vuno = 2 let vdos = 2.0 prepare s3 from "insert into tabla1 values (?,?,?)" execute s3 using vuno,vtres,vdos prepare s4 from "select count(*) from tabla1" declare c4 cursor for s4 open c4 fetch c4 into vuno close c4 message vuno declare c5 cursor for select campo1 from tabla1 open c5 fetch c5 into vuno close c5 message vuno declare c6 cursor for select * from tabla1 where campo1 = 1 for update open c6 fetch c6 into vuno update tabla1 set campo1 = 4, campo2 = "cuatro" where current of c6 #delete from tabla1 where current of c6 close c6 update statistics declare c7 cursor for select * from tabla1 where campo1 != 4 for update open c7 fetch c7 into vuno delete from tabla1 where current of c7 close c7 update statistics end main

CÓDIGO OBJETO: DECLAREFORUPDATE.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class declareforupdate { static int vcuatro ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception {

Page 259: IfxToJava2

259 ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int vuno , vuno1 , vuno2 ; double vdos ; String vtres , vcuatro ; String cad ; vuno = 0; vdos = 0.0; vuno1 = 0; vtres = ""; vuno2 = 0; vcuatro = ""; cad = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(2,0) ) "); PreparedStatement ASG_sp_s1 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (1,'1',1)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s1.executeUpdate(); ASG_sp_s1.close(); vtres = "tabla1" ; cad = "create view vista1 (vcamp1,vcamp2,vcamp3) as " + "select * from " + vtres ; System.out.println(cad ); PreparedStatement ASG_sp_s2 = ASGcondb.retCon().prepareStatement(cad ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s2.executeUpdate(); ASG_sp_s2.close(); vuno = 2 ; vdos = 2 ; PreparedStatement ASG_sp_s3 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (?,?,?)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s3.setInt(1,vuno); ASG_sp_s3.setString(2,vtres); ASG_sp_s3.setDouble(3,vdos); ASG_sp_s3.executeUpdate(); ASG_sp_s3.close(); PreparedStatement ASG_sp_s4 = ASGcondb.retCon().prepareStatement("select count(*) from tabla1" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c4 = ASG_sp_s4.executeQuery(); try { ASG_rsp_c4.next(); vuno = ASG_rsp_c4.getInt(1); } catch (SQLException e) {} ASG_rsp_c4.close(); ASG_sp_s4.close(); System.out.println(vuno ); Statement ASG_sp_c5 = ASGcondb.retCon().createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c5 = ASG_sp_c5.executeQuery("select campo1 from tabla1 "); try { ASG_rsp_c5.next(); vuno = ASG_rsp_c5.getInt(1); } catch (SQLException e) {} ASG_rsp_c5.close(); ASG_sp_c5.close(); System.out.println(vuno ); Statement ASG_sp_c6 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c6 = ASG_sp_c6.executeQuery("select * from tabla1 where campo1 = 1 for update"); try { ASG_rsp_c6.next(); vuno = ASG_rsp_c6.getInt(1); } catch (SQLException e) {} ASGcondb.exeUpdate("update tabla1 set campo1 = 4 , campo2 = 'cuatro' where current of "+ ASG_rsp_c6.getCursorName() ); ASG_rsp_c6.close(); ASG_sp_c6.close(); Statement ASG_sp_c7 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c7 = ASG_sp_c7.executeQuery("select * from tabla1 where campo1 != 4 for update"); try { ASG_rsp_c7.next(); vuno = ASG_rsp_c7.getInt(1); } catch (SQLException e) {} ASGcondb.exeUpdate("delete from tabla1 where current of "+ ASG_rsp_c7.getCursorName() ); ASG_rsp_c7.close(); ASG_sp_c7.close(); } }

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class declareforupdate { static int vcuatro ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int vuno , vuno1 , vuno2 ; double vdos ; String vtres , vcuatro ; String cad ; vuno = 0;

Page 260: IfxToJava2

260 vdos = 0.0; vuno1 = 0; vtres = ""; vuno2 = 0; vcuatro = ""; cad = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(2,0) ) "); PreparedStatement ASG_sp_s1 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (1,'1',1)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s1.executeUpdate(); ASG_sp_s1.close(); vtres = "tabla1" ; cad = "create view vista1 (vcamp1,vcamp2,vcamp3) as " + "select * from " + vtres ; System.out.println(cad ); PreparedStatement ASG_sp_s2 = ASGcondb.retCon().prepareStatement(cad ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s2.executeUpdate(); ASG_sp_s2.close(); vuno = 2 ; vdos = 2 ; PreparedStatement ASG_sp_s3 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (?,?,?)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s3.setInt(1,vuno); ASG_sp_s3.setString(2,vtres); ASG_sp_s3.setDouble(3,vdos); ASG_sp_s3.executeUpdate(); ASG_sp_s3.close(); PreparedStatement ASG_sp_s4 = ASGcondb.retCon().prepareStatement("select count(*) from tabla1" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c4 = ASG_sp_s4.executeQuery(); try { ASG_rsp_c4.next(); vuno = ASG_rsp_c4.getInt(1); } catch (SQLException e) {} ASG_rsp_c4.close(); ASG_sp_s4.close(); System.out.println(vuno ); Statement ASG_sp_c5 = ASGcondb.retCon().createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c5 = ASG_sp_c5.executeQuery("select campo1 from tabla1 "); try { ASG_rsp_c5.next(); vuno = ASG_rsp_c5.getInt(1); } catch (SQLException e) {} ASG_rsp_c5.close(); ASG_sp_c5.close(); System.out.println(vuno ); Statement ASG_sp_c6 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c6 = ASG_sp_c6.executeQuery("select * from tabla1 where campo1 = 1 "); try { ASG_rsp_c6.next(); vuno = ASG_rsp_c6.getInt(1); } catch (SQLException e) {} ASG_rsp_c6.updateShort("campo1",(short)4); ASG_rsp_c6.updateString("campo2","cuatro"); ASG_rsp_c6.updateRow(); ASG_rsp_c6.close(); ASG_sp_c6.close(); Statement ASG_sp_c7 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c7 = ASG_sp_c7.executeQuery("select * from tabla1 where campo1 != 4 "); try { ASG_rsp_c7.next(); vuno = ASG_rsp_c7.getInt(1); } catch (SQLException e) {} ASG_rsp_c7.deleteRow(); ASG_rsp_c7.close(); ASG_sp_c7.close(); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class declareforupdate { static int vcuatro ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int vuno , vuno1 , vuno2 ; double vdos ; String vtres , vcuatro ; String cad ; vuno = 0; vdos = 0.0; vuno1 = 0; vtres = ""; vuno2 = 0; vcuatro = ""; cad = ""; ASGcondb.activaControlError();

Page 261: IfxToJava2

261 ASGcondb.exeUpdate("drop table tabla1 cascade constraints"); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(2,0) ) "); PreparedStatement ASG_sp_s1 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (1,'1',1)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s1.executeUpdate(); ASG_sp_s1.close(); vtres = "tabla1" ; cad = "create view vista1 (vcamp1,vcamp2,vcamp3) as " + "select * from " + vtres ; System.out.println(cad ); PreparedStatement ASG_sp_s2 = ASGcondb.retCon().prepareStatement(cad ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s2.executeUpdate(); ASG_sp_s2.close(); vuno = 2 ; vdos = 2 ; PreparedStatement ASG_sp_s3 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (?,?,?)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s3.setInt(1,vuno); ASG_sp_s3.setString(2,vtres); ASG_sp_s3.setDouble(3,vdos); ASG_sp_s3.executeUpdate(); ASG_sp_s3.close(); PreparedStatement ASG_sp_s4 = ASGcondb.retCon().prepareStatement("select count(*) from tabla1" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c4 = ASG_sp_s4.executeQuery(); try { ASG_rsp_c4.next(); vuno = ASG_rsp_c4.getInt(1); } catch (SQLException e) {} ASG_rsp_c4.close(); ASG_sp_s4.close(); System.out.println(vuno ); Statement ASG_sp_c5 = ASGcondb.retCon().createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c5 = ASG_sp_c5.executeQuery("select campo1 from tabla1 "); try { ASG_rsp_c5.next(); vuno = ASG_rsp_c5.getInt(1); } catch (SQLException e) {} ASG_rsp_c5.close(); ASG_sp_c5.close(); System.out.println(vuno ); Statement ASG_sp_c6 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c6 = ASG_sp_c6.executeQuery("select CAMPO1,CAMPO2,CAMPO3 from tabla1 where campo1 = 1 "); try { ASG_rsp_c6.next(); vuno = ASG_rsp_c6.getInt(1); } catch (SQLException e) {} ASG_rsp_c6.updateObject("campo1",4); ASG_rsp_c6.updateString("campo2","cuatro"); ASG_rsp_c6.updateRow(); ASG_rsp_c6.close(); ASG_sp_c6.close(); Statement ASG_sp_c7 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c7 = ASG_sp_c7.executeQuery("select CAMPO1,CAMPO2,CAMPO3 from tabla1 where campo1 != 4 "); try { ASG_rsp_c7.next(); vuno = ASG_rsp_c7.getInt(1); } catch (SQLException e) {} ASG_rsp_c7.deleteRow(); ASG_rsp_c7.close(); ASG_sp_c7.close(); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class declareforupdate { static int vcuatro ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int vuno , vuno1 , vuno2 ; double vdos ; String vtres , vcuatro ; String cad ; vuno = 0; vdos = 0.0; vuno1 = 0; vtres = ""; vuno2 = 0; vcuatro = ""; cad = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.exeUpdate("drop view vista1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(2,0) ) "); PreparedStatement ASG_sp_s1 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (1,'1',1)" ,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);

Page 262: IfxToJava2

262 ASG_sp_s1.executeUpdate(); ASG_sp_s1.close(); vtres = "tabla1" ; cad = "create view vista1 (vcamp1,vcamp2,vcamp3) as " + "select * from " + vtres ; System.out.println(cad ); PreparedStatement ASG_sp_s2 = ASGcondb.retCon().prepareStatement(cad ,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s2.executeUpdate(); ASG_sp_s2.close(); vuno = 2 ; vdos = 2 ; PreparedStatement ASG_sp_s3 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (?,?,?)" ,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s3.setInt(1,vuno); ASG_sp_s3.setString(2,vtres); ASG_sp_s3.setDouble(3,vdos); ASG_sp_s3.executeUpdate(); ASG_sp_s3.close(); PreparedStatement ASG_sp_s4 = ASGcondb.retCon().prepareStatement("select count(*) from tabla1" ,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c4 = ASG_sp_s4.executeQuery(); try { ASG_rsp_c4.next(); vuno = ASG_rsp_c4.getInt(1); } catch (SQLException e) {} ASG_rsp_c4.close(); ASG_sp_s4.close(); System.out.println(vuno ); Statement ASG_sp_c5 = ASGcondb.retCon().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c5 = ASG_sp_c5.executeQuery("select campo1 from tabla1 "); try { ASG_rsp_c5.next(); vuno = ASG_rsp_c5.getInt(1); } catch (SQLException e) {} ASG_rsp_c5.close(); ASG_sp_c5.close(); System.out.println(vuno ); Statement ASG_sp_c6 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c6 = ASG_sp_c6.executeQuery("select * from tabla1 where campo1 = 1 "); try { ASG_rsp_c6.next(); vuno = ASG_rsp_c6.getInt(1); } catch (SQLException e) {} ASGcondb.exeUpdate("update tabla1 set campo1 = 4 , campo2 = 'cuatro' where current of "+ ASG_rsp_c6.getCursorName() ); ASG_rsp_c6.close(); ASG_sp_c6.close(); Statement ASG_sp_c7 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c7 = ASG_sp_c7.executeQuery("select * from tabla1 where campo1 != 4 "); try { ASG_rsp_c7.next(); vuno = ASG_rsp_c7.getInt(1); } catch (SQLException e) {} ASGcondb.exeUpdate("delete from tabla1 where current of "+ ASG_rsp_c7.getCursorName() ); ASG_rsp_c7.close(); ASG_sp_c7.close(); } }

EJEMPLO SENTENCIA FOREACH-FORUPDATE

CÓDIGO FUENTE INFORMIX-4GL: FOREACHFORUPDATE.4GL database datos define vcuatro smallint main define vuno, vuno1,vuno2 smallint, vdos decimal (10,3), vtres,vcuatro char(20), cad char(200) whenever error continue drop table tabla1 whenever error stop create table tabla1 ( campo1 smallint, campo2 char(10), campo3 decimal(2,0) ) prepare s1 from "insert into tabla1 values (1,'uno',1)" execute s1 let vuno = 2 let vtres = "dos" let vdos = 2.0 prepare s3 from "insert into tabla1 values (?,?,?)" execute s3 using vuno,vtres,vdos insert into tabla1 values (3,'tres',3) insert into tabla1 values (4,'cuatro',4) insert into tabla1 values (5,'cinco',5) insert into tabla1 values (6,'seis',6) insert into tabla1 values (7,'siete',7)

Page 263: IfxToJava2

263 prepare s4 from "select count(*) from tabla1" declare c4 cursor for s4 open c4 fetch c4 into vuno close c4 message "Número de filas: " ,vuno declare c5 cursor for select max(campo1) from tabla1 open c5 fetch c5 into vuno close c5 message "maximo campo1: " ,vuno declare c6 cursor for select * from tabla1 where campo1 > 4 for update of campo1 foreach c6 into vuno,vtres,vdos message "campos: ", vuno," ",vtres,vdos update tabla1 set campo1 = 8 where current of c6 end foreach message "borro fila com campo1 = 4" declare c7 cursor for select * from tabla1 for update foreach c7 into vuno,vtres,vdos message "campos: ", vuno," ",vtres,vdos if vuno = 4 then delete from tabla1 where current of c7 end if end foreach message "Estado final" prepare s8 from "select * from tabla1" declare c8 cursor for s8 foreach c8 into vuno,vtres,vdos message "campos: ", vuno," ",vtres,vdos end foreach end main

CÓDIGO OBJETO: FOREACHFOR.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class foreachforupdate { static int vcuatro ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int vuno , vuno1 , vuno2 ; double vdos ; String vtres , vcuatro ; String cad ; vuno = 0; vdos = 0.0; vuno1 = 0; vtres = ""; vuno2 = 0; vcuatro = ""; cad = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(2,0) ) "); PreparedStatement ASG_sp_s1 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (1,'uno',1)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s1.executeUpdate(); ASG_sp_s1.close(); vuno = 2 ; vtres = "dos" ; vdos = 2 ; PreparedStatement ASG_sp_s3 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (?,?,?)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s3.setInt(1,vuno); ASG_sp_s3.setString(2,vtres); ASG_sp_s3.setDouble(3,vdos); ASG_sp_s3.executeUpdate(); ASG_sp_s3.close(); ASGcondb.exeUpdate("insert into tabla1 values ( 3 , 'tres' , 3 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 4 , 'cuatro' , 4 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 5 , 'cinco' , 5 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 6 , 'seis' , 6 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 7 , 'siete' , 7 ) "); PreparedStatement ASG_sp_s4 = ASGcondb.retCon().prepareStatement("select count(*) from tabla1" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c4 = ASG_sp_s4.executeQuery(); try { ASG_rsp_c4.next(); vuno = ASG_rsp_c4.getInt(1); } catch (SQLException e) {} ASG_rsp_c4.close(); ASG_sp_s4.close(); System.out.println("Número de filas: " + vuno ); Statement ASG_sp_c5 = ASGcondb.retCon().createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c5 = ASG_sp_c5.executeQuery("select max ( campo1 ) from tabla1 "); try {

Page 264: IfxToJava2

264 ASG_rsp_c5.next(); vuno = ASG_rsp_c5.getInt(1); } catch (SQLException e) {} ASG_rsp_c5.close(); ASG_sp_c5.close(); System.out.println("maximo campo1: " + vuno ); Statement ASG_sp_c6 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c6 = ASG_sp_c6.executeQuery("select * from tabla1 where campo1 > 4 for update"); while ( ASG_rsp_c6.next() ) try { vuno = ASG_rsp_c6.getInt(1); vtres = ASG_rsp_c6.getString(2); vdos = ASG_rsp_c6.getDouble(3); System.out.println("campos: " + vuno + " " + vtres + vdos ); ASGcondb.exeUpdate("update tabla1 set campo1 = 8 where current of "+ ASG_rsp_c6.getCursorName() ); } catch (SQLException e) {} ASG_rsp_c6.close(); ASG_sp_c6.close(); System.out.println("borro fila com campo1 = 4" ); Statement ASG_sp_c7 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c7 = ASG_sp_c7.executeQuery("select * from tabla1 for update"); while ( ASG_rsp_c7.next() ) try { vuno = ASG_rsp_c7.getInt(1); vtres = ASG_rsp_c7.getString(2); vdos = ASG_rsp_c7.getDouble(3); System.out.println("campos: " + vuno + " " + vtres + vdos ); if ( vuno == 4 ) { ASGcondb.exeUpdate("delete from tabla1 where current of "+ ASG_rsp_c7.getCursorName() ); } } catch (SQLException e) {} ASG_rsp_c7.close(); ASG_sp_c7.close(); System.out.println("Estado final" ); PreparedStatement ASG_sp_s8 = ASGcondb.retCon().prepareStatement("select * from tabla1" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c8 = ASG_sp_s8.executeQuery(); while ( ASG_rsp_c8.next() ) try { vuno = ASG_rsp_c8.getInt(1); vtres = ASG_rsp_c8.getString(2); vdos = ASG_rsp_c8.getDouble(3); System.out.println("campos: " + vuno + " " + vtres + vdos ); } catch (SQLException e) {} ASG_rsp_c8.close(); ASG_sp_s8.close(); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class foreachforupdate { static int vcuatro ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int vuno , vuno1 , vuno2 ; double vdos ; String vtres , vcuatro ; String cad ; vuno = 0; vdos = 0.0; vuno1 = 0; vtres = ""; vuno2 = 0; vcuatro = ""; cad = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(2,0) ) "); PreparedStatement ASG_sp_s1 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (1,'uno',1)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s1.executeUpdate(); ASG_sp_s1.close(); vuno = 2 ; vtres = "dos" ; vdos = 2 ; PreparedStatement ASG_sp_s3 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (?,?,?)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s3.setInt(1,vuno); ASG_sp_s3.setString(2,vtres); ASG_sp_s3.setDouble(3,vdos); ASG_sp_s3.executeUpdate(); ASG_sp_s3.close(); ASGcondb.exeUpdate("insert into tabla1 values ( 3 , 'tres' , 3 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 4 , 'cuatro' , 4 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 5 , 'cinco' , 5 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 6 , 'seis' , 6 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 7 , 'siete' , 7 ) "); PreparedStatement ASG_sp_s4 = ASGcondb.retCon().prepareStatement("select count(*) from tabla1" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);

Page 265: IfxToJava2

265 ResultSet ASG_rsp_c4 = ASG_sp_s4.executeQuery(); try { ASG_rsp_c4.next(); vuno = ASG_rsp_c4.getInt(1); } catch (SQLException e) {} ASG_rsp_c4.close(); ASG_sp_s4.close(); System.out.println("Número de filas: " + vuno ); Statement ASG_sp_c5 = ASGcondb.retCon().createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c5 = ASG_sp_c5.executeQuery("select max ( campo1 ) from tabla1 "); try { ASG_rsp_c5.next(); vuno = ASG_rsp_c5.getInt(1); } catch (SQLException e) {} ASG_rsp_c5.close(); ASG_sp_c5.close(); System.out.println("maximo campo1: " + vuno ); Statement ASG_sp_c6 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c6 = ASG_sp_c6.executeQuery("select * from tabla1 where campo1 > 4 "); while ( ASG_rsp_c6.next() ) try { vuno = ASG_rsp_c6.getInt(1); vtres = ASG_rsp_c6.getString(2); vdos = ASG_rsp_c6.getDouble(3); System.out.println("campos: " + vuno + " " + vtres + vdos ); ASG_rsp_c6.updateShort("campo1",(short)8); ASG_rsp_c6.updateRow(); } catch (SQLException e) {} ASG_rsp_c6.close(); ASG_sp_c6.close(); System.out.println("borro fila com campo1 = 4" ); Statement ASG_sp_c7 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c7 = ASG_sp_c7.executeQuery("select * from tabla1 "); while ( ASG_rsp_c7.next() ) try { vuno = ASG_rsp_c7.getInt(1); vtres = ASG_rsp_c7.getString(2); vdos = ASG_rsp_c7.getDouble(3); System.out.println("campos: " + vuno + " " + vtres + vdos ); if ( vuno == 4 ) { ASG_rsp_c7.deleteRow(); } } catch (SQLException e) {} ASG_rsp_c7.close(); ASG_sp_c7.close(); System.out.println("Estado final" ); PreparedStatement ASG_sp_s8 = ASGcondb.retCon().prepareStatement("select * from tabla1" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c8 = ASG_sp_s8.executeQuery(); while ( ASG_rsp_c8.next() ) try { vuno = ASG_rsp_c8.getInt(1); vtres = ASG_rsp_c8.getString(2); vdos = ASG_rsp_c8.getDouble(3); System.out.println("campos: " + vuno + " " + vtres + vdos ); } catch (SQLException e) {} ASG_rsp_c8.close(); ASG_sp_s8.close(); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class foreachforupdate { static int vcuatro ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int vuno , vuno1 , vuno2 ; double vdos ; String vtres , vcuatro ; String cad ; vuno = 0; vdos = 0.0; vuno1 = 0; vtres = ""; vuno2 = 0; vcuatro = ""; cad = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(2,0) ) "); PreparedStatement ASG_sp_s1 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (1,'uno',1)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s1.executeUpdate(); ASG_sp_s1.close(); vuno = 2 ; vtres = "dos" ;

Page 266: IfxToJava2

266 vdos = 2 ; PreparedStatement ASG_sp_s3 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (?,?,?)" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s3.setInt(1,vuno); ASG_sp_s3.setString(2,vtres); ASG_sp_s3.setDouble(3,vdos); ASG_sp_s3.executeUpdate(); ASG_sp_s3.close(); ASGcondb.exeUpdate("insert into tabla1 values ( 3 , 'tres' , 3 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 4 , 'cuatro' , 4 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 5 , 'cinco' , 5 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 6 , 'seis' , 6 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 7 , 'siete' , 7 ) "); PreparedStatement ASG_sp_s4 = ASGcondb.retCon().prepareStatement("select count(*) from tabla1" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c4 = ASG_sp_s4.executeQuery(); try { ASG_rsp_c4.next(); vuno = ASG_rsp_c4.getInt(1); } catch (SQLException e) {} ASG_rsp_c4.close(); ASG_sp_s4.close(); System.out.println("Número de filas: " + vuno ); Statement ASG_sp_c5 = ASGcondb.retCon().createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c5 = ASG_sp_c5.executeQuery("select max ( campo1 ) from tabla1 "); try { ASG_rsp_c5.next(); vuno = ASG_rsp_c5.getInt(1); } catch (SQLException e) {} ASG_rsp_c5.close(); ASG_sp_c5.close(); System.out.println("maximo campo1: " + vuno ); Statement ASG_sp_c6 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c6 = ASG_sp_c6.executeQuery("select CAMPO1,CAMPO2,CAMPO3 from tabla1 where campo1 > 4 "); while ( ASG_rsp_c6.next() ) try { vuno = ASG_rsp_c6.getInt(1); vtres = ASG_rsp_c6.getString(2); vdos = ASG_rsp_c6.getDouble(3); System.out.println("campos: " + vuno + " " + vtres + vdos ); ASG_rsp_c6.updateObject("campo1",8); ASG_rsp_c6.updateRow(); } catch (SQLException e) {} ASG_rsp_c6.close(); ASG_sp_c6.close(); System.out.println("borro fila com campo1 = 4" ); Statement ASG_sp_c7 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c7 = ASG_sp_c7.executeQuery("select CAMPO1,CAMPO2,CAMPO3 from tabla1 "); while ( ASG_rsp_c7.next() ) try { vuno = ASG_rsp_c7.getInt(1); vtres = ASG_rsp_c7.getString(2); vdos = ASG_rsp_c7.getDouble(3); System.out.println("campos: " + vuno + " " + vtres + vdos ); if ( vuno == 4 ) { ASG_rsp_c7.deleteRow(); } } catch (SQLException e) {} ASG_rsp_c7.close(); ASG_sp_c7.close(); System.out.println("Estado final" ); PreparedStatement ASG_sp_s8 = ASGcondb.retCon().prepareStatement("select * from tabla1" ,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c8 = ASG_sp_s8.executeQuery(); while ( ASG_rsp_c8.next() ) try { vuno = ASG_rsp_c8.getInt(1); vtres = ASG_rsp_c8.getString(2); vdos = ASG_rsp_c8.getDouble(3); System.out.println("campos: " + vuno + " " + vtres + vdos ); } catch (SQLException e) {} ASG_rsp_c8.close(); ASG_sp_s8.close(); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class foreachforupdate { static int vcuatro ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); int vuno , vuno1 , vuno2 ; double vdos ; String vtres , vcuatro ; String cad ; vuno = 0; vdos = 0.0;

Page 267: IfxToJava2

267 vuno1 = 0; vtres = ""; vuno2 = 0; vcuatro = ""; cad = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla1 ( campo1 smallint , campo2 char(10) , campo3 decimal(2,0) ) "); PreparedStatement ASG_sp_s1 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (1,'uno',1)" ,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s1.executeUpdate(); ASG_sp_s1.close(); vuno = 2 ; vtres = "dos" ; vdos = 2 ; PreparedStatement ASG_sp_s3 = ASGcondb.retCon().prepareStatement("insert into tabla1 values (?,?,?)" ,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ASG_sp_s3.setInt(1,vuno); ASG_sp_s3.setString(2,vtres); ASG_sp_s3.setDouble(3,vdos); ASG_sp_s3.executeUpdate(); ASG_sp_s3.close(); ASGcondb.exeUpdate("insert into tabla1 values ( 3 , 'tres' , 3 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 4 , 'cuatro' , 4 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 5 , 'cinco' , 5 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 6 , 'seis' , 6 ) "); ASGcondb.exeUpdate("insert into tabla1 values ( 7 , 'siete' , 7 ) "); PreparedStatement ASG_sp_s4 = ASGcondb.retCon().prepareStatement("select count(*) from tabla1" ,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c4 = ASG_sp_s4.executeQuery(); try { ASG_rsp_c4.next(); vuno = ASG_rsp_c4.getInt(1); } catch (SQLException e) {} ASG_rsp_c4.close(); ASG_sp_s4.close(); System.out.println("Número de filas: " + vuno ); Statement ASG_sp_c5 = ASGcondb.retCon().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c5 = ASG_sp_c5.executeQuery("select max ( campo1 ) from tabla1 "); try { ASG_rsp_c5.next(); vuno = ASG_rsp_c5.getInt(1); } catch (SQLException e) {} ASG_rsp_c5.close(); ASG_sp_c5.close(); System.out.println("maximo campo1: " + vuno ); Statement ASG_sp_c6 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c6 = ASG_sp_c6.executeQuery("select * from tabla1 where campo1 > 4 "); while ( ASG_rsp_c6.next() ) try { vuno = ASG_rsp_c6.getInt(1); vtres = ASG_rsp_c6.getString(2); vdos = ASG_rsp_c6.getDouble(3); System.out.println("campos: " + vuno + " " + vtres + vdos ); ASGcondb.exeUpdate("update tabla1 set campo1 = 8 where current of "+ ASG_rsp_c6.getCursorName() ); } catch (SQLException e) {} ASG_rsp_c6.close(); ASG_sp_c6.close(); System.out.println("borro fila com campo1 = 4" ); Statement ASG_sp_c7 = ASGcondb.retCon().createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE); ResultSet ASG_rsp_c7 = ASG_sp_c7.executeQuery("select * from tabla1 "); while ( ASG_rsp_c7.next() ) try { vuno = ASG_rsp_c7.getInt(1); vtres = ASG_rsp_c7.getString(2); vdos = ASG_rsp_c7.getDouble(3); System.out.println("campos: " + vuno + " " + vtres + vdos ); if ( vuno == 4 ) { ASGcondb.exeUpdate("delete from tabla1 where current of "+ ASG_rsp_c7.getCursorName() ); } } catch (SQLException e) {} ASG_rsp_c7.close(); ASG_sp_c7.close(); System.out.println("Estado final" ); PreparedStatement ASG_sp_s8 = ASGcondb.retCon().prepareStatement("select * from tabla1" ,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet ASG_rsp_c8 = ASG_sp_s8.executeQuery(); while ( ASG_rsp_c8.next() ) try { vuno = ASG_rsp_c8.getInt(1); vtres = ASG_rsp_c8.getString(2); vdos = ASG_rsp_c8.getDouble(3); System.out.println("campos: " + vuno + " " + vtres + vdos ); } catch (SQLException e) {} ASG_rsp_c8.close(); ASG_sp_s8.close(); } }

EJEMPLO SENTENCIA TIPOS DE DATOS

CÓDIGO FUENTE INFORMIX-4GL: TIPOSDATOS.4GL #tipos de datos admitidos database datos

Page 268: IfxToJava2

268main whenever error continue drop table tabla99 whenever error stop create table tabla99 ( campo1 byte, campo2 char, campo3 char(10), campo4 char(9000), campo5 date, campo6 datetime year to day, campo7 datetime hour to second, campo8 datetime year to second, campo9 decimal, campo10 decimal(10), campo11 decimal(10,2), campo12 float, campo13 integer, campo14 money, campo15 real, campo16 smallint, campo17 text, campo18 varchar(30) ) select campo1,campo2,campo3,campo4,campo5,campo6,campo7,campo8,campo9,campo10,campo11, campo12,campo13,campo14,campo15,campo16,campo17,campo18 from tabla99; end main

CÓDIGO OBJETO: TIPOSDATOS.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class tiposdatos { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla99 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla99 ( campo1 byte , campo2 char(1) , campo3 char(10) , campo4 char(9000) , campo5 date , campo6 date , campo7 datetime hour to second , campo8 datetime year to second , campo9 decimal(16,0) , campo10 decimal(10,0) , campo11 decimal(10,2) , campo12 float , campo13 integer , campo14 decimal(16,2) , campo15 real , campo16 smallint , campo17 text , campo18 varchar(30) ) "); ASGcondb.exeSelectSimple("select campo1 , campo2 , campo3 , campo4 , campo5 , campo6 , campo7 , campo8 , campo9 , campo10 , campo11 , campo12 , campo13 , campo14 , campo15 , campo16 , campo17 , campo18 from tabla99 "); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class tiposdatos { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla99 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla99 ( campo1 image , campo2 char(1) , campo3 char(10) , campo4 text , campo5 datetime , campo6 datetime , campo7 datetime , campo8 datetime , campo9 decimal(16,0) , campo10 decimal(10,0) , campo11 decimal(10,2) , campo12 float , campo13 integer , campo14 decimal(16,2) , campo15 real , campo16 smallint , campo17 text , campo18 varchar(30) ) "); ASGcondb.exeSelectSimple("select campo1 , campo2 , campo3 , campo4 , campo5 , campo6 , campo7 , campo8 , campo9 , campo10 , campo11 , campo12 , campo13 , campo14 , campo15 , campo16 , campo17 , campo18 from tabla99 "); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class tiposdatos { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla99 cascade constraints"); ASGcondb.desactivaControlError();

Page 269: IfxToJava2

269 ASGcondb.exeUpdate("create table tabla99 ( campo1 blob , campo2 char(1) , campo3 char(10) , campo4 long , campo5 date , campo6 date , campo7 date , campo8 timestamp , campo9 decimal(16,0) , campo10 decimal(10,0) , campo11 decimal(10,2) , campo12 float , campo13 integer , campo14 decimal(16,2) , campo15 real , campo16 smallint , campo17 clob , campo18 varchar(30) ) "); ASGcondb.exeSelectSimple("select campo1 , campo2 , campo3 , campo4 , campo5 , campo6 , campo7 , campo8 , campo9 , campo10 , campo11 , campo12 , campo13 , campo14 , campo15 , campo16 , campo17 , campo18 from tabla99 "); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class tiposdatos { private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table tabla99 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table tabla99 ( campo1 blob , campo2 char(1) , campo3 char(10) , campo4 long varchar , campo5 date , campo6 date , campo7 time , campo8 timestamp , campo9 decimal(16,0) , campo10 decimal(10,0) , campo11 decimal(10,2) , campo12 float , campo13 integer , campo14 decimal(16,2) , campo15 real , campo16 smallint , campo17 clob , campo18 varchar(30) ) "); ASGcondb.exeSelectSimple("select campo1 , campo2 , campo3 , campo4 , campo5 , campo6 , campo7 , campo8 , campo9 , campo10 , campo11 , campo12 , campo13 , campo14 , campo15 , campo16 , campo17 , campo18 from tabla99 "); } }

EJEMPLO DE MANEJO DE COLUMNAS Y CONSTANTES PREDEFINIDAS

CÓDIGO FUENTE INFORMIX-4GL: EXPRSQL1.4GL #Expresiones SQL #expresion de manejo de columnas #rowid, acceso campos, subsrting database datos define hola char(30) main define uno char(20), dos date, tres datetime year to fraction whenever error continue drop table prueba1 whenever error stop create table prueba1 ( campo1 char(20), campo2 date, campo3 datetime year to second ) insert into prueba1 values ("esto es una prueba",today,current) select campo1[1,3] into uno from prueba1 message "Primeros tres caracteres del campo: ", uno select informix.prueba1.campo1[2,4] into uno from prueba1 message "Caracteres del 2 al 4 del campo: ", uno select rowid into hola from prueba1 message "Rowid: ", hola end main

CÓDIGO OBJETO: EXPRSQL1.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql1 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; java.sql.Date dos ; java.sql.Timestamp tres ; uno = ""; dos = null; tres = null; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 ");

Page 270: IfxToJava2

270 ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 date , campo3 datetime year to second ) ");

ASGcondb.exeUpdate("insert into prueba1 values ( user , today , current ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select campo1 , campo1[1,3] from prueba1 "); try { ASG_r1.next(); usuario = ASG_r1.getString(1); uno = ASG_r1.getString(2); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("Primeros tres caracteres del campo: " + usuario + "son: " + uno ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select informix.prueba1.campo1[2,4] from prueba1 "); try { ASG_r2.next(); uno = ASG_r2.getString(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("Caracteres del 2 al 4 del campo: " + uno ); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select rowid from prueba1 "); try { ASG_r3.next(); hola = ASG_r3.getString(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("Rowid: " + hola ); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql1 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; java.sql.Date dos ; java.sql.Timestamp tres ; uno = ""; dos = null; tres = null; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 datetime , campo3 datetime ) ");

ASGcondb.exeUpdate("insert into prueba1 values ( user , dateadd(dd,0, datediff(dd,0,getdate())) , getdate() ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select campo1 , substring(campo1,1,3) from prueba1 "); try { ASG_r1.next(); usuario = ASG_r1.getString(1); uno = ASG_r1.getString(2); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("Primeros tres caracteres del campo: " + usuario + "son: " + uno ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select substring(informix.prueba1.campo1,2,3) from prueba1 "); try { ASG_r2.next(); uno = ASG_r2.getString(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("Caracteres del 2 al 4 del campo: " + uno ); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select rowid from prueba1 "); try { ASG_r3.next(); hola = ASG_r3.getString(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("Rowid: " + hola ); } }

OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*;

Page 271: IfxToJava2

271import ASGutil.*; public class exprsql1 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno , usuario ; java.sql.Date dos ; java.sql.Timestamp tres ; uno = ""; dos = null; tres = null; usuario = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 date , campo3 timestamp ) "); ASGcondb.exeUpdate("insert into prueba1 values ( user , to_date(to_char(sysdate,'dd/mm/yyyy')) , sysdate ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select campo1 , substr(campo1,1,3) from prueba1 "); try { ASG_r1.next(); usuario = ASG_r1.getString(1); uno = ASG_r1.getString(2); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("Primeros tres caracteres del campo: " + usuario + "son: " + uno ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select substr(informix.prueba1.campo1,2,3) from informix.prueba1 "); try { ASG_r2.next(); uno = ASG_r2.getString(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("Caracteres del 2 al 4 del campo: " + uno ); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select rowid from prueba1 "); try { ASG_r3.next(); hola = ASG_r3.getString(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("Rowid: " + hola ); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql1 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; java.sql.Date dos ; java.sql.Timestamp tres ; uno = ""; dos = null; tres = null; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 date , campo3 timestamp ) ");

ASGcondb.exeUpdate("insert into prueba1 values ( user , current date , current timestamp ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select campo1 , substr(campo1,1,3) from prueba1 "); try { ASG_r1.next(); usuario = ASG_r1.getString(1); uno = ASG_r1.getString(2); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("Primeros tres caracteres del campo: " + usuario + "son: " + uno ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select substr(informix.prueba1.campo1,2,3) from prueba1 "); try { ASG_r2.next(); uno = ASG_r2.getString(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close();

Page 272: IfxToJava2

272 System.out.println("Caracteres del 2 al 4 del campo: " + uno ); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select rowid from prueba1 "); try { ASG_r3.next(); hola = ASG_r3.getString(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("Rowid: " + hola ); } }

EJEMPLO DE MANEJO DE LITERALES, CONSTANTES Y VARIABLES

CÓDIGO FUENTE INFORMIX-4GL: EXPRSQL2.4GL #Expresiones SQL #expresion de manejo de constantes #literales, vbles, y ctes. database datos define hola char(30) main define uno char(20), dos,fecha date, tres datetime year to fraction, cuatro integer, cinco decimal(12,2) let uno = "hola mundo" let cuatro = 24 let dos = today; let tres = current; let cinco = cuatro; let tres = "2007-07-22 12:33:20.444"; let dos = "22/07/2007"; let fecha = 40000 message "campo1: ", uno message "campo2: ", dos message "campo3: ", tres message "campo4: ", cuatro message "campo5: ", cinco message "--------------------------" whenever error continue drop table prueba1 whenever error stop create table prueba1 ( campo1 char(20), campo2 date, campo3 datetime year to fraction, campo4 integer, campo5 decimal(12,2) ) insert into prueba1 values ("esto es una prueba",today,current,12,12.3) insert into prueba1 values (uno,dos,tres,cuatro,12.3) insert into prueba1 values (uno,fecha,tres,cuatro,1.3) insert into prueba1 values (uno,"15/08/2006","2007-07-21 13:44:30.23",cuatro,12.3) insert into prueba1 values (uno,"15/08/2006",datetime (2007-07-22 12:33:20.444) year to fraction,cuatro,12.3) select campo1,campo2,campo3,campo4,campo5 into uno,dos,tres,cuatro,cinco from prueba1 message "campo1: ", uno message "campo2: ", dos message "campo3: ", tres message "campo4: ", cuatro message "campo5: ", cinco end main

CÓDIGO OBJETO: EXPRSQL2.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql2 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; java.sql.Date dos , fecha ; java.sql.Timestamp tres ; int cuatro ; double cinco ; cuatro = 0; cinco = 0.0; fecha = null;

Page 273: IfxToJava2

273 uno = ""; dos = null; tres = null; uno = "hola mundo" ; cuatro = 24 ; dos = new Date(new java.util.Date().getTime()) ; tres = new Timestamp(new java.util.Date().getTime()) ; cinco = cuatro ; tres = ASGfaux.fechahora("2007-07-22 12:33:20.444") ; dos = ASGfaux.fecha("22/07/2007") ; fecha = ASGfaux.cteIntToFechaJ(40000) ; System.out.println("campo1: " + uno ); System.out.println("campo2: " + ASGfaux.formato_fecha(dos) ); System.out.println("campo3: " + tres ); System.out.println("campo4: " + cuatro ); System.out.println("campo5: " + cinco ); System.out.println("--------------------------" ); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 date , campo3 datetime year to fraction , campo4 integer , campo5 decimal(12,2) ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , today , current , 12 , 12.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , {d '"+ dos +"'} , {ts '"+ tres +"'} , "+ cuatro +" , 12.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , {d '"+ fecha +"'} , {ts '"+ tres +"'} , "+ cuatro +" , 1.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , '15/08/2006' , '2007-07-21 13:44:30.23' , "+ cuatro +" , 12.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , '15/08/2006' , datetime ( 2007-7-22 12:33:20.444 ) year to fraction , "+ cuatro +" , 12.3 ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select campo1 , campo2 , campo3 , campo4 , campo5 from prueba1 "); try { ASG_r1.next(); uno = ASG_r1.getString(1); dos = ASG_r1.getDate(2); tres = ASG_r1.getTimestamp(3); cuatro = ASG_r1.getInt(4); cinco = ASG_r1.getDouble(5); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("campo1: " + uno ); System.out.println("campo2: " + ASGfaux.formato_fecha(dos) ); System.out.println("campo3: " + tres ); System.out.println("campo4: " + cuatro ); System.out.println("campo5: " + cinco ); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql2 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; java.sql.Date dos , fecha ; java.sql.Timestamp tres ; int cuatro ; double cinco ; cuatro = 0; cinco = 0.0; fecha = null; uno = ""; dos = null; tres = null; uno = "hola mundo" ; cuatro = 24 ; dos = new Date(new java.util.Date().getTime()) ; tres = new Timestamp(new java.util.Date().getTime()) ; cinco = cuatro ; tres = ASGfaux.fechahora("2007-07-22 12:33:20.444") ; dos = ASGfaux.fecha("22/07/2007") ; fecha = ASGfaux.cteIntToFechaJ(40000) ; System.out.println("campo1: " + uno ); System.out.println("campo2: " + ASGfaux.formato_fecha(dos) ); System.out.println("campo3: " + tres ); System.out.println("campo4: " + cuatro ); System.out.println("campo5: " + cinco ); System.out.println("--------------------------" ); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 datetime , campo3 datetime , campo4 integer , campo5 decimal(12,2) ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , dateadd(dd,0, datediff(dd,0,getdate())) , getdate() , 12 , 12.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , {d '"+ dos +"'} , {ts '"+ tres +"'} , "+ cuatro +" , 12.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , {d '"+ fecha +"'} , {ts '"+ tres +"'} , "+ cuatro +" , 1.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , convert(datetime,'15/08/2006',103) , convert(datetime,'2007-07-21 13:44:30.23',121) , "+ cuatro +" , 12.3 ) ");

Page 274: IfxToJava2

274 ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , convert(datetime,'15/08/2006',103) , convert(datetime,'2007-7-22 12:33:20.444 ',121) , "+ cuatro +" , 12.3 ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select campo1 , campo2 , campo3 , campo4 , campo5 from prueba1 "); try { ASG_r1.next(); uno = ASG_r1.getString(1); dos = ASG_r1.getDate(2); tres = ASG_r1.getTimestamp(3); cuatro = ASG_r1.getInt(4); cinco = ASG_r1.getDouble(5); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("campo1: " + uno ); System.out.println("campo2: " + ASGfaux.formato_fecha(dos) ); System.out.println("campo3: " + tres ); System.out.println("campo4: " + cuatro ); System.out.println("campo5: " + cinco ); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql2 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; java.sql.Date dos , fecha ; java.sql.Timestamp tres ; int cuatro ; double cinco ; cuatro = 0; cinco = 0.0; fecha = null; uno = ""; dos = null; tres = null; uno = "hola mundo" ; cuatro = 24 ; dos = new Date(new java.util.Date().getTime()) ; tres = new Timestamp(new java.util.Date().getTime()) ; cinco = cuatro ; tres = ASGfaux.fechahora("2007-07-22 12:33:20.444") ; dos = ASGfaux.fecha("22/07/2007") ; fecha = ASGfaux.cteIntToFechaJ(40000) ; System.out.println("campo1: " + uno ); System.out.println("campo2: " + ASGfaux.formato_fecha(dos) ); System.out.println("campo3: " + tres ); System.out.println("campo4: " + cuatro ); System.out.println("campo5: " + cinco ); System.out.println("--------------------------" ); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 date , campo3 timestamp , campo4 integer , campo5 decimal(12,2) ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , to_date(to_char(sysdate,'dd/mm/yyyy')) , sysdate , 12 , 12.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , {d '"+ dos +"'} , {ts '"+ tres +"'} , "+ cuatro +" , 12.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , {d '"+ fecha +"'} , {ts '"+ tres +"'} , "+ cuatro +" , 1.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , to_date('15/08/2006','dd/mm/yyyy') , timestamp '2007-07-21 13:44:30.23' , "+ cuatro +" , 12.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , to_date('15/08/2006','dd/mm/yyyy') , timestamp '2007-7-22 12:33:20.444 ' , "+ cuatro +" , 12.3 ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select campo1 , campo2 , campo3 , campo4 , campo5 from prueba1 "); try { ASG_r1.next(); uno = ASG_r1.getString(1); dos = ASG_r1.getDate(2); tres = ASG_r1.getTimestamp(3); cuatro = ASG_r1.getInt(4); cinco = ASG_r1.getDouble(5); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("campo1: " + uno ); System.out.println("campo2: " + ASGfaux.formato_fecha(dos) ); System.out.println("campo3: " + tres ); System.out.println("campo4: " + cuatro ); System.out.println("campo5: " + cinco ); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*;

Page 275: IfxToJava2

275import ASGutil.*; public class exprsql2 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; java.sql.Date dos , fecha ; java.sql.Timestamp tres ; int cuatro ; double cinco ; cuatro = 0; cinco = 0.0; fecha = null; uno = ""; dos = null; tres = null; uno = "hola mundo" ; cuatro = 24 ; dos = new Date(new java.util.Date().getTime()) ; tres = new Timestamp(new java.util.Date().getTime()) ; cinco = cuatro ; tres = ASGfaux.fechahora("2007-07-22 12:33:20.444") ; dos = ASGfaux.fecha("22/07/2007") ; fecha = ASGfaux.cteIntToFechaJ(40000) ; System.out.println("campo1: " + uno ); System.out.println("campo2: " + ASGfaux.formato_fecha(dos) ); System.out.println("campo3: " + tres ); System.out.println("campo4: " + cuatro ); System.out.println("campo5: " + cinco ); System.out.println("--------------------------" ); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 date , campo3 timestamp , campo4 integer , campo5 decimal(12,2) ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , current date , current timestamp , 12 , 12.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , {d '"+ dos +"'} , {ts '"+ tres +"'} , "+ cuatro +" , 12.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , {d '"+ fecha +"'} , {ts '"+ tres +"'} , "+ cuatro +" , 1.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , date('15/08/2006') , '2007-07-21 13:44:30.23' , "+ cuatro +" , 12.3 ) "); ASGcondb.exeUpdate("insert into prueba1 values ( '"+ uno +"' , date('15/08/2006') , '2007-7-22 12:33:20.444 ' , "+ cuatro +" , 12.3 ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select campo1 , campo2 , campo3 , campo4 , campo5 from prueba1 "); try { ASG_r1.next(); uno = ASG_r1.getString(1); dos = ASG_r1.getDate(2); tres = ASG_r1.getTimestamp(3); cuatro = ASG_r1.getInt(4); cinco = ASG_r1.getDouble(5); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("campo1: " + uno ); System.out.println("campo2: " + ASGfaux.formato_fecha(dos) ); System.out.println("campo3: " + tres ); System.out.println("campo4: " + cuatro ); System.out.println("campo5: " + cinco ); } }

EJEMPLO FUNCIONES DE MANEJO DE FECHAS

CÓDIGO FUENTE INFORMIX-4GL: EXPRSQL4.4GL #Expresiones SQL #Funciones Sql trtamientod e fechas #day,year,month,weekday,date,mdy,etc. database datos define hola char(30) main define fecha1,fecha2 date, fecha3 datetime year to fraction, dia,mes,diaw,anio integer, cinco decimal(12,2) let dia = day(today) let mes = month(today); let diaw = weekday(today) let anio = year(today) let fecha1 = date("31/12/2006") let fecha1 = date(today) let fecha2 = mdy(month(today),dia,year(today)) let fecha3 = datetime (2007-07-22 12:33:20.444) year to fraction message "dia: ", dia message "mes: ", mes message "dia de la semana: ", diaw message "año: ", anio message "fecha: ", fecha1

Page 276: IfxToJava2

276 message "fecha: ", fecha2 message "fecha: ", fecha3 message "-----------------------" whenever error continue drop table prueba2 whenever error stop create table prueba2 ( dia smallint, mes smallint, diaw smallint, anio smallint, fecha1 date, fecha2 date ) insert into prueba2 values(11,1,1,2005,today,today) insert into prueba2 values(11,1,1,2005,"31/12/2006",'31/12/2006') select day(today),month(today),weekday(today),year(today) ,date("31/12/2006") ,mdy(12,31,2006) into dia,mes,diaw,anio,fecha1,fecha2 from prueba2 message "dia: ", dia message "mes: ", mes message "dia de la semana: ", diaw message "año: ", anio message "fecha: ", fecha1 message "fecha: ", fecha2 update prueba2 set dia = day(today), mes = month(today), diaw = weekday(today), anio = year(today), fecha1 = date("31/12/2006"), fecha2 = mdy(3,dia,anio) select * into dia,mes,diaw,anio,fecha1,fecha2 from prueba2 message "-----------------------" message "dia: ", dia message "mes: ", mes message "dia de la semana: ", diaw message "año: ", anio message "fecha: ", fecha1 message "fecha: ", fecha2 end main

CÓDIGO OBJETO: EXPRSQL4JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql4 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); java.sql.Date fecha1 , fecha2 ; java.sql.Timestamp fecha3 ; int dia , mes , diaw , anio ; double cinco ; cinco = 0.0; fecha3 = null; fecha2 = null; mes = 0; diaw = 0; fecha1 = null; dia = 0; anio = 0; dia = ASGfaux.day( new Date(new java.util.Date().getTime()) ) ; mes = ASGfaux.month( new Date(new java.util.Date().getTime()) ) ; diaw = ASGfaux.dayweek( new Date(new java.util.Date().getTime()) ) - 1 ; anio = ASGfaux.year( new Date(new java.util.Date().getTime()) ) ; fecha1 = ASGfaux.fecha( ASGfaux.fecha("31/12/2006") ) ; fecha1 = ASGfaux.fecha( new Date(new java.util.Date().getTime()) ) ; fecha2 = ASGfaux.mdy ( ASGfaux.month( new Date(new java.util.Date().getTime()) ) , dia , ASGfaux.year( new Date(new java.util.Date().getTime()) ) ) ; fecha3 = ASGfaux.fechahora ( "2007-7-22 12:33:20.444" ) ; System.out.println("dia: " + dia ); System.out.println("mes: " + mes ); System.out.println("dia de la semana: " + diaw ); System.out.println("año: " + anio ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha1) ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha2) ); System.out.println("fecha: " + fecha3 ); System.out.println("-----------------------" ); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba2 ( dia smallint , mes smallint , diaw smallint , anio smallint , fecha1 date , fecha2 date ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 11 , 1 , 1 , 2005 , today , today ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 11 , 1 , 1 , 2005 , '31/12/2006' , '31/12/2006' ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement();

Page 277: IfxToJava2

277 ResultSet ASG_r1 = ASG_st1.executeQuery("select day ( today ) , month ( today ) , weekday ( today ) , year ( today ) , date( '31/12/2006' ) , mdy( 12 ,31 ,2006 ) from prueba2 "); try { ASG_r1.next(); dia = ASG_r1.getInt(1); mes = ASG_r1.getInt(2); diaw = ASG_r1.getInt(3); anio = ASG_r1.getInt(4); fecha1 = ASG_r1.getDate(5); fecha2 = ASG_r1.getDate(6); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("dia: " + dia ); System.out.println("mes: " + mes ); System.out.println("dia de la semana: " + diaw ); System.out.println("año: " + anio ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha1) ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha2) ); ASGcondb.exeUpdate("update prueba2 set dia = day ( today ) , mes = month ( today ) , diaw = weekday ( today ) , anio = year ( today ) , fecha1 = date( '31/12/2006' ) , fecha2 = mdy( 3 ,dia ,anio ) "); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select * from prueba2 "); try { ASG_r2.next(); dia = ASG_r2.getInt(1); mes = ASG_r2.getInt(2); diaw = ASG_r2.getInt(3); anio = ASG_r2.getInt(4); fecha1 = ASG_r2.getDate(5); fecha2 = ASG_r2.getDate(6); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("-----------------------" ); System.out.println("dia: " + dia ); System.out.println("mes: " + mes ); System.out.println("dia de la semana: " + diaw ); System.out.println("año: " + anio ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha1) ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha2) ); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql4 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); java.sql.Date fecha1 , fecha2 ; java.sql.Timestamp fecha3 ; int dia , mes , diaw , anio ; double cinco ; cinco = 0.0; fecha3 = null; fecha2 = null; mes = 0; diaw = 0; fecha1 = null; dia = 0; anio = 0; dia = ASGfaux.day( new Date(new java.util.Date().getTime()) ) ; mes = ASGfaux.month( new Date(new java.util.Date().getTime()) ) ; diaw = ASGfaux.dayweek( new Date(new java.util.Date().getTime()) ) - 1 ; anio = ASGfaux.year( new Date(new java.util.Date().getTime()) ) ; fecha1 = ASGfaux.fecha( ASGfaux.fecha("31/12/2006") ) ; fecha1 = ASGfaux.fecha( new Date(new java.util.Date().getTime()) ) ; fecha2 = ASGfaux.mdy ( ASGfaux.month( new Date(new java.util.Date().getTime()) ) , dia , ASGfaux.year( new Date(new java.util.Date().getTime()) ) ) ; fecha3 = ASGfaux.fechahora ( "2007-7-22 12:33:20.444" ) ; System.out.println("dia: " + dia ); System.out.println("mes: " + mes ); System.out.println("dia de la semana: " + diaw ); System.out.println("año: " + anio ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha1) ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha2) ); System.out.println("fecha: " + fecha3 ); System.out.println("-----------------------" ); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba2 ( dia smallint , mes smallint , diaw smallint , anio smallint , fecha1 datetime , fecha2 datetime ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 11 , 1 , 1 , 2005 , dateadd(dd,0, datediff(dd,0,getdate())) , dateadd(dd,0, datediff(dd,0,getdate())) ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 11 , 1 , 1 , 2005 , convert(datetime,'31/12/2006',103) , convert(datetime,'31/12/2006',103) ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select day ( dateadd(dd,0, datediff(dd,0,getdate())) ) , month ( dateadd(dd,0, datediff(dd,0,getdate())) ) , datepart ( dw, dateadd(dd,0, datediff(dd,0,getdate())) ) % 7 , year ( dateadd(dd,0, datediff(dd,0,getdate())) ) , convert(datetime, convert(datetime,'31/12/2006',103) ,103) , convert(datetime, '"+31+'/'+12+'/'+2006+"',103 ) from prueba2 "); try {

Page 278: IfxToJava2

278 ASG_r1.next(); dia = ASG_r1.getInt(1); mes = ASG_r1.getInt(2); diaw = ASG_r1.getInt(3); anio = ASG_r1.getInt(4); fecha1 = ASG_r1.getDate(5); fecha2 = ASG_r1.getDate(6); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("dia: " + dia ); System.out.println("mes: " + mes ); System.out.println("dia de la semana: " + diaw ); System.out.println("año: " + anio ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha1) ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha2) ); ASGcondb.exeUpdate("update prueba2 set dia = day ( dateadd(dd,0, datediff(dd,0,getdate())) ) , mes = month ( dateadd(dd,0, datediff(dd,0,getdate())) ) , diaw = datepart ( dw, dateadd(dd,0, datediff(dd,0,getdate())) ) % 7 , anio = year ( dateadd(dd,0, datediff(dd,0,getdate())) ) , fecha1 = convert(datetime, convert(datetime,'31/12/2006',103) ,103) , fecha2 = convert(datetime, '"+dia+'/'+3+'/'+anio+"',103 ) "); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select * from prueba2 "); try { ASG_r2.next(); dia = ASG_r2.getInt(1); mes = ASG_r2.getInt(2); diaw = ASG_r2.getInt(3); anio = ASG_r2.getInt(4); fecha1 = ASG_r2.getDate(5); fecha2 = ASG_r2.getDate(6); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("-----------------------" ); System.out.println("dia: " + dia ); System.out.println("mes: " + mes ); System.out.println("dia de la semana: " + diaw ); System.out.println("año: " + anio ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha1) ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha2) ); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql4 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); java.sql.Date fecha1 , fecha2 ; java.sql.Timestamp fecha3 ; int dia , mes , diaw , anio ; double cinco ; cinco = 0.0; fecha3 = null; fecha2 = null; mes = 0; diaw = 0; fecha1 = null; dia = 0; anio = 0; dia = ASGfaux.day( new Date(new java.util.Date().getTime()) ) ; mes = ASGfaux.month( new Date(new java.util.Date().getTime()) ) ; diaw = ASGfaux.dayweek( new Date(new java.util.Date().getTime()) ) - 1 ; anio = ASGfaux.year( new Date(new java.util.Date().getTime()) ) ; fecha1 = ASGfaux.fecha( ASGfaux.fecha("31/12/2006") ) ; fecha1 = ASGfaux.fecha( new Date(new java.util.Date().getTime()) ) ; fecha2 = ASGfaux.mdy ( ASGfaux.month( new Date(new java.util.Date().getTime()) ) , dia , ASGfaux.year( new Date(new java.util.Date().getTime()) ) ) ; fecha3 = ASGfaux.fechahora ( "2007-7-22 12:33:20.444" ) ; System.out.println("dia: " + dia ); System.out.println("mes: " + mes ); System.out.println("dia de la semana: " + diaw ); System.out.println("año: " + anio ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha1) ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha2) ); System.out.println("fecha: " + fecha3 ); System.out.println("-----------------------" ); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba2 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba2 ( dia smallint , mes smallint , diaw smallint , anio smallint , fecha1 date , fecha2 date ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 11 , 1 , 1 , 2005 , to_date(to_char(sysdate,'dd/mm/yyyy')) , to_date(to_char(sysdate,'dd/mm/yyyy')) ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 11 , 1 , 1 , 2005 , to_date('31/12/2006','dd/mm/yyyy') , to_date('31/12/2006','dd/mm/yyyy') ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select to_char ( to_date(to_char(sysdate,'dd/mm/yyyy')) ,'DD' ) , to_char ( to_date(to_char(sysdate,'dd/mm/yyyy')) ,'MM' ) , mod(to_char ( to_date(to_char(sysdate,'dd/mm/yyyy')) ,'D' ),7) , to_char ( to_date(to_char(sysdate,'dd/mm/yyyy')) ,'YYYY' ) , to_date( to_date('31/12/2006','dd/mm/yyyy') ,'dd/mm/yyyy') , to_date( '"+31+'/'+12+'/'+2006+"' ) from prueba2 "); try { ASG_r1.next(); dia = ASG_r1.getInt(1);

Page 279: IfxToJava2

279 mes = ASG_r1.getInt(2); diaw = ASG_r1.getInt(3); anio = ASG_r1.getInt(4); fecha1 = ASG_r1.getDate(5); fecha2 = ASG_r1.getDate(6); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("dia: " + dia ); System.out.println("mes: " + mes ); System.out.println("dia de la semana: " + diaw ); System.out.println("año: " + anio ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha1) ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha2) ); ASGcondb.exeUpdate("update prueba2 set dia = to_char ( to_date(to_char(sysdate,'dd/mm/yyyy')) ,'DD' ) , mes = to_char ( to_date(to_char(sysdate,'dd/mm/yyyy')) ,'MM' ) , diaw = mod(to_char ( to_date(to_char(sysdate,'dd/mm/yyyy')) ,'D' ),7) , anio = to_char ( to_date(to_char(sysdate,'dd/mm/yyyy')) ,'YYYY' ) , fecha1 = to_date( to_date('31/12/2006','dd/mm/yyyy') ,'dd/mm/yyyy') , fecha2 = to_date( '"+dia+'/'+3+'/'+anio+"' ) "); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select * from prueba2 "); try { ASG_r2.next(); dia = ASG_r2.getInt(1); mes = ASG_r2.getInt(2); diaw = ASG_r2.getInt(3); anio = ASG_r2.getInt(4); fecha1 = ASG_r2.getDate(5); fecha2 = ASG_r2.getDate(6); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("-----------------------" ); System.out.println("dia: " + dia ); System.out.println("mes: " + mes ); System.out.println("dia de la semana: " + diaw ); System.out.println("año: " + anio ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha1) ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha2) ); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql4 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); java.sql.Date fecha1 , fecha2 ; java.sql.Timestamp fecha3 ; int dia , mes , diaw , anio ; double cinco ; cinco = 0.0; fecha3 = null; fecha2 = null; mes = 0; diaw = 0; fecha1 = null; dia = 0; anio = 0; dia = ASGfaux.day( new Date(new java.util.Date().getTime()) ) ; mes = ASGfaux.month( new Date(new java.util.Date().getTime()) ) ; diaw = ASGfaux.dayweek( new Date(new java.util.Date().getTime()) ) - 1 ; anio = ASGfaux.year( new Date(new java.util.Date().getTime()) ) ; fecha1 = ASGfaux.fecha( ASGfaux.fecha("31/12/2006") ) ; fecha1 = ASGfaux.fecha( new Date(new java.util.Date().getTime()) ) ; fecha2 = ASGfaux.mdy ( ASGfaux.month( new Date(new java.util.Date().getTime()) ) , dia , ASGfaux.year( new Date(new java.util.Date().getTime()) ) ) ; fecha3 = ASGfaux.fechahora ( "2007-7-22 12:33:20.444" ) ; System.out.println("dia: " + dia ); System.out.println("mes: " + mes ); System.out.println("dia de la semana: " + diaw ); System.out.println("año: " + anio ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha1) ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha2) ); System.out.println("fecha: " + fecha3 ); System.out.println("-----------------------" ); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba2 ( dia smallint , mes smallint , diaw smallint , anio smallint , fecha1 date , fecha2 date ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 11 , 1 , 1 , 2005 , current date , current date ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 11 , 1 , 1 , 2005 , date('31/12/2006') , date('31/12/2006') ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select day ( current date ) , month ( current date ) , dayofweek ( current date ) - 1 , year ( current date ) , date( date('31/12/2006') ) , date( '"+31+'/'+12+'/'+2006+"' ) from prueba2 "); try { ASG_r1.next(); dia = ASG_r1.getInt(1); mes = ASG_r1.getInt(2); diaw = ASG_r1.getInt(3); anio = ASG_r1.getInt(4); fecha1 = ASG_r1.getDate(5); fecha2 = ASG_r1.getDate(6);

Page 280: IfxToJava2

280 } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("dia: " + dia ); System.out.println("mes: " + mes ); System.out.println("dia de la semana: " + diaw ); System.out.println("año: " + anio ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha1) ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha2) ); ASGcondb.exeUpdate("update prueba2 set dia = day ( current date ) , mes = month ( current date ) , diaw = dayofweek ( current date ) - 1 , anio = year ( current date ) , fecha1 = date( date('31/12/2006') ) , fecha2 = date( '"+dia+'/'+3+'/'+anio+"' ) "); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select * from prueba2 "); try { ASG_r2.next(); dia = ASG_r2.getInt(1); mes = ASG_r2.getInt(2); diaw = ASG_r2.getInt(3); anio = ASG_r2.getInt(4); fecha1 = ASG_r2.getDate(5); fecha2 = ASG_r2.getDate(6); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("-----------------------" ); System.out.println("dia: " + dia ); System.out.println("mes: " + mes ); System.out.println("dia de la semana: " + diaw ); System.out.println("año: " + anio ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha1) ); System.out.println("fecha: " + ASGfaux.formato_fecha(fecha2) ); } }

EJEMPLO DE FUNCIONES MATEMÁTICAS

CÓDIGO FUENTE INFORMIX-4GL: EXPRSQL5.4GL #Expresiones SQL #Funciones Sql #length, hex, round, trunc database datos define hola char(30) main define uno char(20), dos,cuatro decimal(10,2), tres char(2) whenever error continue drop table prueba1 whenever error stop create table prueba1 ( campo1 char(20), campo2 decimal(10,2), campo3 int ) insert into prueba1 values ("esto es una prueba",10.55,16) select length(campo1) into uno from prueba1 message "Longitud del campo: ", uno select round(campo2), trunc(campo2) into dos,cuatro from prueba1 message "Redondeo: ", dos, " Truncado: ",cuatro select hex(campo3) into tres from prueba1 message "hex: ", tres end main

CÓDIGO OBJETO: EXPRSQL5.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql5 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; double dos , cuatro ; String tres ; cuatro = 0.0; uno = ""; dos = 0.0; tres = ""; ASGcondb.activaControlError();

Page 281: IfxToJava2

281 ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 decimal(10,2) , campo3 integer ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , 10.55 , 16 ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select length( campo1 ) from prueba1 "); try { ASG_r1.next(); uno = ASG_r1.getString(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("Longitud del campo: " + uno ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select round ( campo2 ,0 ) , trunc ( campo2 ,0 ) from prueba1 "); try { ASG_r2.next(); dos = ASG_r2.getDouble(1); cuatro = ASG_r2.getDouble(2); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("Redondeo: " + dos + " Truncado: " + cuatro ); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select hex ( campo3 ) from prueba1 "); try { ASG_r3.next(); tres = ASG_r3.getString(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("hex: " + tres ); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql5 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; double dos , cuatro ; String tres ; cuatro = 0.0; uno = ""; dos = 0.0; tres = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 decimal(10,2) , campo3 integer ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , 10.55 , 16 ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select len( campo1 ) from prueba1 "); try { ASG_r1.next(); uno = ASG_r1.getString(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("Longitud del campo: " + uno ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select round ( campo2 ,0 ) , round ( campo2 ,0 ,1 ) from prueba1 "); try { ASG_r2.next(); dos = ASG_r2.getDouble(1); cuatro = ASG_r2.getDouble(2); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("Redondeo: " + dos + " Truncado: " + cuatro ); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select dbo.inttohex ( campo3 ) from prueba1 "); try { ASG_r3.next(); tres = ASG_r3.getString(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("hex: " + tres ); } }

Page 282: IfxToJava2

282

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql5 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; double dos , cuatro ; String tres ; cuatro = 0.0; uno = ""; dos = 0.0; tres = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 decimal(10,2) , campo3 integer ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , 10.55 , 16 ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select length(rtrim( campo1 ) ) from prueba1 "); try { ASG_r1.next(); uno = ASG_r1.getString(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("Longitud del campo: " + uno ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select round ( campo2 ,0 ) , trunc ( campo2 ,0 ) from prueba1 "); try { ASG_r2.next(); dos = ASG_r2.getDouble(1); cuatro = ASG_r2.getDouble(2); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("Redondeo: " + dos + " Truncado: " + cuatro ); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select to_char ( campo3 ,'XXXXXXXX' ) from prueba1 "); try { ASG_r3.next(); tres = ASG_r3.getString(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("hex: " + tres ); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql5 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; double dos , cuatro ; String tres ; cuatro = 0.0; uno = ""; dos = 0.0; tres = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 decimal(10,2) , campo3 integer ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , 10.55 , 16 ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select length(rtrim( campo1 ) ) from prueba1 "); try { ASG_r1.next(); uno = ASG_r1.getString(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("Longitud del campo: " + uno ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select round ( campo2 ,0 ) , trunc ( campo2 ,0 ) from prueba1 "); try { ASG_r2.next();

Page 283: IfxToJava2

283 dos = ASG_r2.getDouble(1); cuatro = ASG_r2.getDouble(2); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("Redondeo: " + dos + " Truncado: " + cuatro ); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select hex ( campo3 ) from prueba1 "); try { ASG_r3.next(); tres = ASG_r3.getString(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("hex: " + tres ); } }

EJEMPLO DE FUNCIONES AGREGADAS

CÓDIGO FUENTE INFORMIX-4GL: EXPRSQL6.4GL #Expresiones SQL #Funciones Sql agregadas #count,max,min,sum, y avg database datos define hola char(30) main define uno char(20), dos,cuatro decimal(10,2), tres char(20) whenever error continue drop table prueba1 whenever error stop create table prueba1 ( campo1 char(20), campo2 decimal(10,2), campo3 char(20) ) insert into prueba1 values ("esto es una prueba",10,"16") insert into prueba1 values ("esto es una prueba",20,"16") insert into prueba1 values ("esto es una prueba",20,"16") insert into prueba1 values ("esto es una prueba",20,"16") insert into prueba1 values ("esto es una prueba",10,"16") insert into prueba1 values ("esto es una prueba",10,"16") select count(*) into dos from prueba1 message "Número de filas: ", dos select count(unique campo1) into dos from prueba1 message "Número de filas con campo1 diferente: ", dos select avg(campo2) into dos from prueba1 message "Valor medio campo2: ",dos select max(campo2) into dos from prueba1 message "Valor maximo campo2: ",dos select min(campo2) into dos from prueba1 message "Valor minimo campo2: ",dos select sum(campo2) into dos from prueba1 message "Suma valores campo2: ",dos end main

CÓDIGO OBJETO: EXPRSQL6.JAVA import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql6 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; double dos , cuatro ; String tres ; cuatro = 0.0; uno = ""; dos = 0.0; tres = ""; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 decimal(10,2) , campo3 char(20) ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , 10 , '16' ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , 20 , '16' ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , 20 , '16' ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , 20 , '16' ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , 10 , '16' ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'esto es una prueba' , 10 , '16' ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select count ( * ) from prueba1 ");

Page 284: IfxToJava2

284 try { ASG_r1.next(); dos = ASG_r1.getDouble(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("Número de filas: " + dos ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select count ( distinct campo1 ) from prueba1 "); try { ASG_r2.next(); dos = ASG_r2.getDouble(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("Número de filas con campo1 diferente: " + dos ); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select avg ( campo2 ) from prueba1 "); try { ASG_r3.next(); dos = ASG_r3.getDouble(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("Valor medio campo2: " + dos ); Statement ASG_st4 = ASGcondb.retCon().createStatement(); ResultSet ASG_r4 = ASG_st4.executeQuery("select max ( campo2 ) from prueba1 "); try { ASG_r4.next(); dos = ASG_r4.getDouble(1); } catch (SQLException e) {} ASG_r4.close(); ASG_st4.close(); System.out.println("Valor maximo campo2: " + dos ); Statement ASG_st5 = ASGcondb.retCon().createStatement(); ResultSet ASG_r5 = ASG_st5.executeQuery("select min ( campo2 ) from prueba1 "); try { ASG_r5.next(); dos = ASG_r5.getDouble(1); } catch (SQLException e) {} ASG_r5.close(); ASG_st5.close(); System.out.println("Valor minimo campo2: " + dos ); Statement ASG_st6 = ASGcondb.retCon().createStatement(); ResultSet ASG_r6 = ASG_st6.executeQuery("select sum ( campo2 ) from prueba1 "); try { ASG_r6.next(); dos = ASG_r6.getDouble(1); } catch (SQLException e) {} ASG_r6.close(); ASG_st6.close(); System.out.println("Suma valores campo2: " + dos ); } }

EJEMPLO DE FUNCION WEEKDAY

CÓDIGO FUENTE INFORMIX-4GL: EXPRSQL7.4GL #Expresiones SQL #Funciones Sql #Tratamiento de weekday database datos define hola char(30) main define fecha1, fecha2 date, l,m,x,j,v,s,d,h integer, cinco decimal(12,2) let l = weekday("03/09/2007") let m =weekday("04/09/2007") let x =weekday("05/09/2007") let j =weekday("06/09/2007") let v =weekday("07/09/2007") let s =weekday("08/09/2007") let d =weekday("09/09/2007") let h =weekday(today) message "lunes: ",l message "martes: ",m message "miercoles: ",x message "jueves: ",j message "viernes: ",v message "sabado: ",s message "domingo: ",d message "hoy: ",h message "-----------------------" whenever error continue drop table prueba2

Page 285: IfxToJava2

285 whenever error stop create table prueba2 ( dia smallint, mes smallint, diaw smallint, anio smallint, fecha1 date, fecha2 date ) insert into prueba2 values(1,1,1,1,today,today) select weekday("03/09/2007"),weekday("04/09/2007"),weekday("05/09/2007"),weekday("06/09/2007"),weekday("07/09/2007"),weekday("08/09/2007"),weekday("09/09/2007"),weekday(today) into l,m,x,j,v,s,d,h from prueba2 message "lunes: ",l message "martes: ",m message "miercoles: ",x message "jueves: ",j message "viernes: ",v message "sabado: ",s message "domingo: ",d message "hoy: ",h end main

CÓDIGO OBJETO: EXPRSQL7.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql7 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); java.sql.Date fecha1 , fecha2 ; int l , m , x , j , v , s , d , h ; double cinco ; d = 0; m = 0; cinco = 0.0; v = 0; h = 0; l = 0; fecha2 = null; x = 0; j = 0; fecha1 = null; s = 0; l = ASGfaux.dayweek( ASGfaux.fecha("03/09/2007") ) - 1 ; m = ASGfaux.dayweek( ASGfaux.fecha("04/09/2007") ) - 1 ; x = ASGfaux.dayweek( ASGfaux.fecha("05/09/2007") ) - 1 ; j = ASGfaux.dayweek( ASGfaux.fecha("06/09/2007") ) - 1 ; v = ASGfaux.dayweek( ASGfaux.fecha("07/09/2007") ) - 1 ; s = ASGfaux.dayweek( ASGfaux.fecha("08/09/2007") ) - 1 ; d = ASGfaux.dayweek( ASGfaux.fecha("09/09/2007") ) - 1 ; h = ASGfaux.dayweek( new Date(new java.util.Date().getTime()) ) - 1 ; System.out.println("lunes: " + l ); System.out.println("martes: " + m ); System.out.println("miercoles: " + x ); System.out.println("jueves: " + j ); System.out.println("viernes: " + v ); System.out.println("sabado: " + s ); System.out.println("domingo: " + d ); System.out.println("hoy: " + h ); System.out.println("-----------------------" ); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba2 ( dia smallint , mes smallint , diaw smallint , anio smallint , fecha1 date , fecha2 date ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 1 , 1 , 1 , 1 , today , today ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select weekday ( '03/09/2007' ) , weekday ( '04/09/2007' ) , weekday ( '05/09/2007' ) , weekday ( '06/09/2007' ) , weekday ( '07/09/2007' ) , weekday ( '08/09/2007' ) , weekday ( '09/09/2007' ) , weekday ( today ) from prueba2 "); try { ASG_r1.next(); l = ASG_r1.getInt(1); m = ASG_r1.getInt(2); x = ASG_r1.getInt(3); j = ASG_r1.getInt(4); v = ASG_r1.getInt(5); s = ASG_r1.getInt(6); d = ASG_r1.getInt(7); h = ASG_r1.getInt(8); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("lunes: " + l ); System.out.println("martes: " + m ); System.out.println("miercoles: " + x );

Page 286: IfxToJava2

286 System.out.println("jueves: " + j ); System.out.println("viernes: " + v ); System.out.println("sabado: " + s ); System.out.println("domingo: " + d ); System.out.println("hoy: " + h ); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql7 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); java.sql.Date fecha1 , fecha2 ; int l , m , x , j , v , s , d , h ; double cinco ; d = 0; m = 0; cinco = 0.0; v = 0; h = 0; l = 0; fecha2 = null; x = 0; j = 0; fecha1 = null; s = 0; l = ASGfaux.dayweek( ASGfaux.fecha("03/09/2007") ) - 1 ; m = ASGfaux.dayweek( ASGfaux.fecha("04/09/2007") ) - 1 ; x = ASGfaux.dayweek( ASGfaux.fecha("05/09/2007") ) - 1 ; j = ASGfaux.dayweek( ASGfaux.fecha("06/09/2007") ) - 1 ; v = ASGfaux.dayweek( ASGfaux.fecha("07/09/2007") ) - 1 ; s = ASGfaux.dayweek( ASGfaux.fecha("08/09/2007") ) - 1 ; d = ASGfaux.dayweek( ASGfaux.fecha("09/09/2007") ) - 1 ; h = ASGfaux.dayweek( new Date(new java.util.Date().getTime()) ) - 1 ; System.out.println("lunes: " + l ); System.out.println("martes: " + m ); System.out.println("miercoles: " + x ); System.out.println("jueves: " + j ); System.out.println("viernes: " + v ); System.out.println("sabado: " + s ); System.out.println("domingo: " + d ); System.out.println("hoy: " + h ); System.out.println("-----------------------" ); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba2 ( dia smallint , mes smallint , diaw smallint , anio smallint , fecha1 datetime , fecha2 datetime ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 1 , 1 , 1 , 1 , dateadd(dd,0, datediff(dd,0,getdate())) , dateadd(dd,0, datediff(dd,0,getdate())) ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select datepart ( dw, convert(datetime,'03/09/2007',103) ) % 7 , datepart ( dw, convert(datetime,'04/09/2007',103) ) % 7 , datepart ( dw, convert(datetime,'05/09/2007',103) ) % 7 , datepart ( dw, convert(datetime,'06/09/2007',103) ) % 7 , datepart ( dw, convert(datetime,'07/09/2007',103) ) % 7 , datepart ( dw, convert(datetime,'08/09/2007',103) ) % 7 , datepart ( dw, convert(datetime,'09/09/2007',103) ) % 7 , datepart ( dw, dateadd(dd,0, datediff(dd,0,getdate())) ) % 7 from prueba2 "); try { ASG_r1.next(); l = ASG_r1.getInt(1); m = ASG_r1.getInt(2); x = ASG_r1.getInt(3); j = ASG_r1.getInt(4); v = ASG_r1.getInt(5); s = ASG_r1.getInt(6); d = ASG_r1.getInt(7); h = ASG_r1.getInt(8); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("lunes: " + l ); System.out.println("martes: " + m ); System.out.println("miercoles: " + x ); System.out.println("jueves: " + j ); System.out.println("viernes: " + v ); System.out.println("sabado: " + s ); System.out.println("domingo: " + d ); System.out.println("hoy: " + h ); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql7 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos");

Page 287: IfxToJava2

287 ASGcondb.HayTransac(); java.sql.Date fecha1 , fecha2 ; int l , m , x , j , v , s , d , h ; double cinco ; d = 0; m = 0; cinco = 0.0; v = 0; h = 0; l = 0; fecha2 = null; x = 0; j = 0; fecha1 = null; s = 0; l = ASGfaux.dayweek( ASGfaux.fecha("03/09/2007") ) - 1 ; m = ASGfaux.dayweek( ASGfaux.fecha("04/09/2007") ) - 1 ; x = ASGfaux.dayweek( ASGfaux.fecha("05/09/2007") ) - 1 ; j = ASGfaux.dayweek( ASGfaux.fecha("06/09/2007") ) - 1 ; v = ASGfaux.dayweek( ASGfaux.fecha("07/09/2007") ) - 1 ; s = ASGfaux.dayweek( ASGfaux.fecha("08/09/2007") ) - 1 ; d = ASGfaux.dayweek( ASGfaux.fecha("09/09/2007") ) - 1 ; h = ASGfaux.dayweek( new Date(new java.util.Date().getTime()) ) - 1 ; System.out.println("lunes: " + l ); System.out.println("martes: " + m ); System.out.println("miercoles: " + x ); System.out.println("jueves: " + j ); System.out.println("viernes: " + v ); System.out.println("sabado: " + s ); System.out.println("domingo: " + d ); System.out.println("hoy: " + h ); System.out.println("-----------------------" ); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba2 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba2 ( dia smallint , mes smallint , diaw smallint , anio smallint , fecha1 date , fecha2 date ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 1 , 1 , 1 , 1 , to_date(to_char(sysdate,'dd/mm/yyyy')) , to_date(to_char(sysdate,'dd/mm/yyyy')) ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select mod(to_char ( to_date('03/09/2007','dd/mm/yyyy') ,'D' ),7) , mod(to_char ( to_date('04/09/2007','dd/mm/yyyy') ,'D' ),7) , mod(to_char ( to_date('05/09/2007','dd/mm/yyyy') ,'D' ),7) , mod(to_char ( to_date('06/09/2007','dd/mm/yyyy') ,'D' ),7) , mod(to_char ( to_date('07/09/2007','dd/mm/yyyy') ,'D' ),7) , mod(to_char ( to_date('08/09/2007','dd/mm/yyyy') ,'D' ),7) , mod(to_char ( to_date('09/09/2007','dd/mm/yyyy') ,'D' ),7) , mod(to_char ( to_date(to_char(sysdate,'dd/mm/yyyy')) ,'D' ),7) from prueba2 "); try { ASG_r1.next(); l = ASG_r1.getInt(1); m = ASG_r1.getInt(2); x = ASG_r1.getInt(3); j = ASG_r1.getInt(4); v = ASG_r1.getInt(5); s = ASG_r1.getInt(6); d = ASG_r1.getInt(7); h = ASG_r1.getInt(8); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("lunes: " + l ); System.out.println("martes: " + m ); System.out.println("miercoles: " + x ); System.out.println("jueves: " + j ); System.out.println("viernes: " + v ); System.out.println("sabado: " + s ); System.out.println("domingo: " + d ); System.out.println("hoy: " + h ); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class exprsql7 { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); java.sql.Date fecha1 , fecha2 ; int l , m , x , j , v , s , d , h ; double cinco ; d = 0; m = 0; cinco = 0.0; v = 0; h = 0; l = 0; fecha2 = null; x = 0; j = 0; fecha1 = null; s = 0; l = ASGfaux.dayweek( ASGfaux.fecha("03/09/2007") ) - 1 ; m = ASGfaux.dayweek( ASGfaux.fecha("04/09/2007") ) - 1 ; x = ASGfaux.dayweek( ASGfaux.fecha("05/09/2007") ) - 1 ; j = ASGfaux.dayweek( ASGfaux.fecha("06/09/2007") ) - 1 ; v = ASGfaux.dayweek( ASGfaux.fecha("07/09/2007") ) - 1 ; s = ASGfaux.dayweek( ASGfaux.fecha("08/09/2007") ) - 1 ; d = ASGfaux.dayweek( ASGfaux.fecha("09/09/2007") ) - 1 ; h = ASGfaux.dayweek( new Date(new java.util.Date().getTime()) ) - 1 ;

Page 288: IfxToJava2

288 System.out.println("lunes: " + l ); System.out.println("martes: " + m ); System.out.println("miercoles: " + x ); System.out.println("jueves: " + j ); System.out.println("viernes: " + v ); System.out.println("sabado: " + s ); System.out.println("domingo: " + d ); System.out.println("hoy: " + h ); System.out.println("-----------------------" ); ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba2 ( dia smallint , mes smallint , diaw smallint , anio smallint , fecha1 date , fecha2 date ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 1 , 1 , 1 , 1 , current date , current date ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select dayofweek ( date('03/09/2007') ) - 1 , dayofweek ( date('04/09/2007') ) - 1 , dayofweek ( date('05/09/2007') ) - 1 , dayofweek ( date('06/09/2007') ) - 1 , dayofweek ( date('07/09/2007') ) - 1 , dayofweek ( date('08/09/2007') ) - 1 , dayofweek ( date('09/09/2007') ) - 1 , dayofweek ( current date ) - 1 from prueba2 "); try { ASG_r1.next(); l = ASG_r1.getInt(1); m = ASG_r1.getInt(2); x = ASG_r1.getInt(3); j = ASG_r1.getInt(4); v = ASG_r1.getInt(5); s = ASG_r1.getInt(6); d = ASG_r1.getInt(7); h = ASG_r1.getInt(8); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("lunes: " + l ); System.out.println("martes: " + m ); System.out.println("miercoles: " + x ); System.out.println("jueves: " + j ); System.out.println("viernes: " + v ); System.out.println("sabado: " + s ); System.out.println("domingo: " + d ); System.out.println("hoy: " + h ); } }

EJEMPLO DE MANEJO DE OPERACIONES SOBRE EXPRESIONES

CÓDIGO FUENTE INFORMIX-4GL: OPERSQL.4GL #Operaciones sobre expresiones Sql database datos define hola char(20) main define uno char(20), dos smallint, tres decimal(10,2), fecha, fecha2 date whenever error continue drop table prueba1 drop table prueba2 whenever error stop create table prueba1 ( campo1 char(20), campo2 smallint, campo3 decimal(10,2), campo4 date, campo5 date ) create table prueba2 ( campo5 char(20), campo4 smallint, campo1 decimal(10,2), campo2 date, campo3 date ) insert into prueba1 values ("prueba",1,8.2,today,"31/12/2007") insert into prueba1 values ("otra Cosa",2,3,today,"31/12/2007") insert into prueba1 values ("Prueba",3,1,today,today) insert into prueba2 values ("prueba",2,10,today,today) select tabla99.campo2 from informix.tabla99 select prueba1.campo2 from prueba1 select informix.tabla99.campo2 from tabla99 select informix.prueba1.campo2 from informix.prueba1 select e.campo1, f.campo1, g.campo1 from prueba1 e, prueba2 f, tabla99 g select CAMPO3 + campo2 + 1 into tres from prueba1 where campo2 = 1 message "resultado sumar dos números: ", tres select campo4 + campo2 + 1 into fecha from prueba1 where campo2 = 1 message "resultado sumar fecha y entero: ", fecha let dos = 2 select campo4 + dos into fecha from prueba1 where campo2 = 1 message "resultado sumar fecha y entero: ", fecha select "31/12/2007" - campo4 into dos from prueba1 where campo2 = 1

Page 289: IfxToJava2

289 message "resultado restar dos fechas: ",dos select fecha - campo4 into dos from prueba1 where campo2 = 1 message "resultado restar dos fechas: ",dos insert into prueba1 values ("prueba",3,5,fecha,today) select fecha - campo4 into dos from prueba1 where campo2 = 2 message "resultado de restar dos fechas: ", dos select campo5 - campo4 into dos from prueba1 where campo2 = 2 message "resultado de restar dos fechas: ", dos select fecha - today into dos from prueba1 where campo2 = 2 message "resultado de restar dos fechas: ", dos select campo4 into fecha2 from prueba1 where campo2 = 1 message "fecha fila1: ", fecha2 select campo4 into fecha2 from prueba1 where campo2 = 2 message "fecha fila2: ", fecha2 select campo4 into fecha2 from prueba1 where campo2 = 3 message "fecha fila3: ", fecha2 select count(campo2) into dos from prueba1 where campo4 < fecha message "número de filas con fecha menor que: ", fecha, " = ", dos select count(*) into dos from prueba1 where campo2 between 1 and 2 message "número de filas con campo2 entre 1 y 2: ",dos select campo3 into tres from prueba1 where exists (select campo2 from prueba2 where campo4 = prueba1.campo2) message "resultado exist: ", tres select campo3 into tres from prueba1 where campo2 in (select campo4 from prueba2) message "resultado in: ", tres select sum(campo3) into tres from prueba1 where campo2 in (1,2,3,4,6) message "resultado in: ", tres select sum(campo3) into tres from prueba1 where campo2 not in (select campo4 from prueba2) message "resultado not in: ", tres select count(*) into dos from prueba1 where campo1 is null message "filas con valores nulos: ",dos select count(*) into dos from prueba1 where campo1 is not null message "filas con valores no nulos: ",dos select sum(campo3) into tres from prueba1 where campo2 > any (select campo4 from prueba2 where campo4 = prueba1.campo2) message "resultado any: ", tres select sum(campo3) into tres from prueba1 where campo2 >= some (select campo4 from prueba2 where campo4 = prueba1.campo2) message "resultado some: ", tres select sum(campo3) into tres from prueba1 where campo2 > all (select campo4 from prueba2 where campo4 = prueba1.campo2) message "resultado all: ", tres select count(campo2) into dos from prueba1 where campo1 matches "P*" escape '$' message "filas que cumplen la condicion matches P* escape $ : ",dos select count(*) into dos from prueba1 where campo1 not like "P%" message "filas que cumplen la condicion not like P% : ",dos select count(*) into dos from prueba1 where campo1 not like "_rueba" message "filas que cumplen la condicion not like _rueba : ",dos select count(*) into dos from prueba1 where campo1 matches "?[a-z]ueba" message "filas que cumplen la condicion matches ?[a-z]ueba : ",dos select count(*) into dos from prueba1 where campo1 matches "?[^r-s]ueba" message "filas que cumplen la condicion matches ?[^r-s]ueba : ",dos select count(*) into dos from prueba1 where campo1 matches "?[rs]ueba" message "filas que cumplen la condicion matches ?[rs]ueba : ",dos select count(*) into dos from prueba1 where campo1 matches "?[^rs]ueba" message "filas que cumplen la condicion matches ?[^rs]ueba : ",dos select count(*) into dos from prueba1 where campo1 matches "?[a-z123456789A-Z]ueba" message "filas que cumplen la condicion matches ?[a-z123456789A-Z]ueba : ",dos select count(*) into dos from prueba1 where campo1 matches "?[a-zA-Z123456789]ueba" message "filas que cumplen la condicion matches ?[a-zA-Z123456789]ueba : ",dos end main

CÓDIGO OBJETO: OPERSQL.4GL

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class opersql { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos");

Page 290: IfxToJava2

290 ASGcondb.HayTransac(); String uno ; int dos ; double tres ; java.sql.Date fecha , fecha2 ; fecha2 = null; fecha = null; uno = ""; dos = 0; tres = 0.0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.exeUpdate("drop table prueba2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 smallint , campo3 decimal(10,2) , campo4 date , campo5 date ) "); ASGcondb.exeUpdate("create table prueba2 ( campo5 char(20) , campo4 smallint , campo1 decimal(10,2) , campo2 date , campo3 date ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'prueba' , 1 , 8.2 , today , '31/12/2007' ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'otra Cosa' , 2 , 3 , today , '31/12/2007' ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'Prueba' , 3 , 1 , today , today ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 'prueba' , 2 , 10 , today , today ) "); ASGcondb.exeSelectSimple("select tabla99.campo2 from tabla99 "); ASGcondb.exeSelectSimple("select prueba1.campo2 from prueba1 "); ASGcondb.exeSelectSimple("select informix.tabla99.campo2 from tabla99 "); ASGcondb.exeSelectSimple("select informix.prueba1.campo2 from prueba1 "); ASGcondb.exeSelectSimple("select e.campo1 , f.campo1 , g.campo1 from prueba1 e , prueba2 f , tabla99 g "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select campo3 + campo2 + 1 from prueba1 where campo2 = 1 "); try { ASG_r1.next(); tres = ASG_r1.getDouble(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("resultado sumar dos números: " + tres ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select campo4 + campo2 + 1 from prueba1 where campo2 = 1 "); try { ASG_r2.next(); fecha = ASG_r2.getDate(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("resultado sumar fecha y entero: " + ASGfaux.formato_fecha(fecha) ); dos = 2 ; Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select campo4 + "+ dos +" from prueba1 where campo2 = 1 "); try { ASG_r3.next(); fecha = ASG_r3.getDate(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("resultado sumar fecha y entero: " + ASGfaux.formato_fecha(fecha) ); Statement ASG_st4 = ASGcondb.retCon().createStatement(); ResultSet ASG_r4 = ASG_st4.executeQuery("select '31/12/2007' - campo4 from prueba1 where campo2 = 1 "); try { ASG_r4.next(); dos = ASG_r4.getInt(1); } catch (SQLException e) {} ASG_r4.close(); ASG_st4.close(); System.out.println("resultado restar dos fechas: " + dos ); Statement ASG_st5 = ASGcondb.retCon().createStatement(); ResultSet ASG_r5 = ASG_st5.executeQuery("select {d '"+ fecha +"'} - campo4 from prueba1 where campo2 = 1 "); try { ASG_r5.next(); dos = ASG_r5.getInt(1); } catch (SQLException e) {} ASG_r5.close(); ASG_st5.close(); System.out.println("resultado restar dos fechas: " + dos ); ASGcondb.exeUpdate("insert into prueba1 values ( 'prueba' , 3 , 5 , {d '"+ fecha +"'} , today ) "); Statement ASG_st6 = ASGcondb.retCon().createStatement(); ResultSet ASG_r6 = ASG_st6.executeQuery("select {d '"+ fecha +"'} - campo4 from prueba1 where campo2 = 2 "); try { ASG_r6.next(); dos = ASG_r6.getInt(1); } catch (SQLException e) {} ASG_r6.close(); ASG_st6.close(); System.out.println("resultado de restar dos fechas: " + dos ); Statement ASG_st7 = ASGcondb.retCon().createStatement(); ResultSet ASG_r7 = ASG_st7.executeQuery("select campo5 - campo4 from prueba1 where campo2 = 2 "); try { ASG_r7.next(); dos = ASG_r7.getInt(1); } catch (SQLException e) {} ASG_r7.close(); ASG_st7.close(); System.out.println("resultado de restar dos fechas: " + dos ); Statement ASG_st8 = ASGcondb.retCon().createStatement();

Page 291: IfxToJava2

291 ResultSet ASG_r8 = ASG_st8.executeQuery("select {d '"+ fecha +"'} - today from prueba1 where campo2 = 2 "); try { ASG_r8.next(); dos = ASG_r8.getInt(1); } catch (SQLException e) {} ASG_r8.close(); ASG_st8.close(); System.out.println("resultado de restar dos fechas: " + dos ); Statement ASG_st9 = ASGcondb.retCon().createStatement(); ResultSet ASG_r9 = ASG_st9.executeQuery("select campo4 from prueba1 where campo2 = 1 "); try { ASG_r9.next(); fecha2 = ASG_r9.getDate(1); } catch (SQLException e) {} ASG_r9.close(); ASG_st9.close(); System.out.println("fecha fila1: " + ASGfaux.formato_fecha(fecha2) ); Statement ASG_st10 = ASGcondb.retCon().createStatement(); ResultSet ASG_r10 = ASG_st10.executeQuery("select campo4 from prueba1 where campo2 = 2 "); try { ASG_r10.next(); fecha2 = ASG_r10.getDate(1); } catch (SQLException e) {} ASG_r10.close(); ASG_st10.close(); System.out.println("fecha fila2: " + ASGfaux.formato_fecha(fecha2) ); Statement ASG_st11 = ASGcondb.retCon().createStatement(); ResultSet ASG_r11 = ASG_st11.executeQuery("select campo4 from prueba1 where campo2 = 3 "); try { ASG_r11.next(); fecha2 = ASG_r11.getDate(1); } catch (SQLException e) {} ASG_r11.close(); ASG_st11.close(); System.out.println("fecha fila3: " + ASGfaux.formato_fecha(fecha2) ); Statement ASG_st12 = ASGcondb.retCon().createStatement(); ResultSet ASG_r12 = ASG_st12.executeQuery("select count ( campo2 ) from prueba1 where campo4 < {d '"+ fecha +"'} "); try { ASG_r12.next(); dos = ASG_r12.getInt(1); } catch (SQLException e) {} ASG_r12.close(); ASG_st12.close(); System.out.println("número de filas con fecha menor que: " + ASGfaux.formato_fecha(fecha) + " = " + dos ); Statement ASG_st13 = ASGcondb.retCon().createStatement(); ResultSet ASG_r13 = ASG_st13.executeQuery("select count ( * ) from prueba1 where campo2 between 1 and 2 "); try { ASG_r13.next(); dos = ASG_r13.getInt(1); } catch (SQLException e) {} ASG_r13.close(); ASG_st13.close(); System.out.println("número de filas con campo2 entre 1 y 2: " + dos ); Statement ASG_st14 = ASGcondb.retCon().createStatement(); ResultSet ASG_r14 = ASG_st14.executeQuery("select campo3 from prueba1 where exists ( select campo2 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r14.next(); tres = ASG_r14.getDouble(1); } catch (SQLException e) {} ASG_r14.close(); ASG_st14.close(); System.out.println("resultado exist: " + tres ); Statement ASG_st15 = ASGcondb.retCon().createStatement(); ResultSet ASG_r15 = ASG_st15.executeQuery("select campo3 from prueba1 where campo2 in ( select campo4 from prueba2 ) "); try { ASG_r15.next(); tres = ASG_r15.getDouble(1); } catch (SQLException e) {} ASG_r15.close(); ASG_st15.close(); System.out.println("resultado in: " + tres ); Statement ASG_st16 = ASGcondb.retCon().createStatement(); ResultSet ASG_r16 = ASG_st16.executeQuery("select sum ( campo3 ) from prueba1 where campo2 in ( 1 , 2 , 3 , 4 , 6 ) "); try { ASG_r16.next(); tres = ASG_r16.getDouble(1); } catch (SQLException e) {} ASG_r16.close(); ASG_st16.close(); System.out.println("resultado in: " + tres ); Statement ASG_st17 = ASGcondb.retCon().createStatement(); ResultSet ASG_r17 = ASG_st17.executeQuery("select sum ( campo3 ) from prueba1 where campo2 not in ( select campo4 from prueba2 ) "); try { ASG_r17.next();

Page 292: IfxToJava2

292 tres = ASG_r17.getDouble(1); } catch (SQLException e) {} ASG_r17.close(); ASG_st17.close(); System.out.println("resultado not in: " + tres ); Statement ASG_st18 = ASGcondb.retCon().createStatement(); ResultSet ASG_r18 = ASG_st18.executeQuery("select count ( * ) from prueba1 where campo1 is null "); try { ASG_r18.next(); dos = ASG_r18.getInt(1); } catch (SQLException e) {} ASG_r18.close(); ASG_st18.close(); System.out.println("filas con valores nulos: " + dos ); Statement ASG_st19 = ASGcondb.retCon().createStatement(); ResultSet ASG_r19 = ASG_st19.executeQuery("select count ( * ) from prueba1 where campo1 is not null "); try { ASG_r19.next(); dos = ASG_r19.getInt(1); } catch (SQLException e) {} ASG_r19.close(); ASG_st19.close(); System.out.println("filas con valores no nulos: " + dos ); Statement ASG_st20 = ASGcondb.retCon().createStatement(); ResultSet ASG_r20 = ASG_st20.executeQuery("select sum ( campo3 ) from prueba1 where campo2 > any ( select campo4 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r20.next(); tres = ASG_r20.getDouble(1); } catch (SQLException e) {} ASG_r20.close(); ASG_st20.close(); System.out.println("resultado any: " + tres ); Statement ASG_st21 = ASGcondb.retCon().createStatement(); ResultSet ASG_r21 = ASG_st21.executeQuery("select sum ( campo3 ) from prueba1 where campo2 >= some ( select campo4 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r21.next(); tres = ASG_r21.getDouble(1); } catch (SQLException e) {} ASG_r21.close(); ASG_st21.close(); System.out.println("resultado some: " + tres ); Statement ASG_st22 = ASGcondb.retCon().createStatement(); ResultSet ASG_r22 = ASG_st22.executeQuery("select sum ( campo3 ) from prueba1 where campo2 > all ( select campo4 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r22.next(); tres = ASG_r22.getDouble(1); } catch (SQLException e) {} ASG_r22.close(); ASG_st22.close(); System.out.println("resultado all: " + tres ); Statement ASG_st23 = ASGcondb.retCon().createStatement(); ResultSet ASG_r23 = ASG_st23.executeQuery("select count ( campo2 ) from prueba1 where campo1 matches 'P*' "); try { ASG_r23.next(); dos = ASG_r23.getInt(1); } catch (SQLException e) {} ASG_r23.close(); ASG_st23.close(); System.out.println("filas que cumplen la condicion matches P* escape $ : " + dos ); Statement ASG_st24 = ASGcondb.retCon().createStatement(); ResultSet ASG_r24 = ASG_st24.executeQuery("select count ( * ) from prueba1 where campo1 not like 'P%' escape '\\' "); try { ASG_r24.next(); dos = ASG_r24.getInt(1); } catch (SQLException e) {} ASG_r24.close(); ASG_st24.close(); System.out.println("filas que cumplen la condicion not like P% : " + dos ); Statement ASG_st25 = ASGcondb.retCon().createStatement(); ResultSet ASG_r25 = ASG_st25.executeQuery("select count ( * ) from prueba1 where campo1 not like '_rueba' escape '\\' "); try { ASG_r25.next(); dos = ASG_r25.getInt(1); } catch (SQLException e) {} ASG_r25.close(); ASG_st25.close(); System.out.println("filas que cumplen la condicion not like _rueba : " + dos ); Statement ASG_st26 = ASGcondb.retCon().createStatement(); ResultSet ASG_r26 = ASG_st26.executeQuery("select count ( * ) from prueba1 where campo1 matches '?[a-z]ueba' "); try { ASG_r26.next(); dos = ASG_r26.getInt(1); } catch (SQLException e) {} ASG_r26.close(); ASG_st26.close();

Page 293: IfxToJava2

293 System.out.println("filas que cumplen la condicion matches ?[a-z]ueba : " + dos ); Statement ASG_st27 = ASGcondb.retCon().createStatement(); ResultSet ASG_r27 = ASG_st27.executeQuery("select count ( * ) from prueba1 where campo1 matches '?[^r-s]ueba' "); try { ASG_r27.next(); dos = ASG_r27.getInt(1); } catch (SQLException e) {} ASG_r27.close(); ASG_st27.close(); System.out.println("filas que cumplen la condicion matches ?[^r-s]ueba : " + dos ); Statement ASG_st28 = ASGcondb.retCon().createStatement(); ResultSet ASG_r28 = ASG_st28.executeQuery("select count ( * ) from prueba1 where campo1 matches '?[rs]ueba' "); try { ASG_r28.next(); dos = ASG_r28.getInt(1); } catch (SQLException e) {} ASG_r28.close(); ASG_st28.close(); System.out.println("filas que cumplen la condicion matches ?[rs]ueba : " + dos ); Statement ASG_st29 = ASGcondb.retCon().createStatement(); ResultSet ASG_r29 = ASG_st29.executeQuery("select count ( * ) from prueba1 where campo1 matches '?[^rs]ueba' "); try { ASG_r29.next(); dos = ASG_r29.getInt(1); } catch (SQLException e) {} ASG_r29.close(); ASG_st29.close(); System.out.println("filas que cumplen la condicion matches ?[^rs]ueba : " + dos ); Statement ASG_st30 = ASGcondb.retCon().createStatement(); ResultSet ASG_r30 = ASG_st30.executeQuery("select count ( * ) from prueba1 where campo1 matches '?[a-z123456789A-Z]ueba' "); try { ASG_r30.next(); dos = ASG_r30.getInt(1); } catch (SQLException e) {} ASG_r30.close(); ASG_st30.close(); System.out.println("filas que cumplen la condicion matches ?[a-z123456789A-Z]ueba : " + dos ); Statement ASG_st31 = ASGcondb.retCon().createStatement(); ResultSet ASG_r31 = ASG_st31.executeQuery("select count ( * ) from prueba1 where campo1 matches '?[a-zA-Z123456789]ueba' "); try { ASG_r31.next(); dos = ASG_r31.getInt(1); } catch (SQLException e) {} ASG_r31.close(); ASG_st31.close(); System.out.println("filas que cumplen la condicion matches ?[a-zA-Z123456789]ueba : " + dos ); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class opersql { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; int dos ; double tres ; java.sql.Date fecha , fecha2 ; fecha2 = null; fecha = null; uno = ""; dos = 0; tres = 0.0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.exeUpdate("drop table prueba2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 smallint , campo3 decimal(10,2) , campo4 datetime , campo5 datetime ) "); ASGcondb.exeUpdate("create table prueba2 ( campo5 char(20) , campo4 smallint , campo1 decimal(10,2) , campo2 datetime , campo3 datetime ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'prueba' , 1 , 8.2 , dateadd(dd,0, datediff(dd,0,getdate())) , convert(datetime,'31/12/2007',103) ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'otra Cosa' , 2 , 3 , dateadd(dd,0, datediff(dd,0,getdate())) , convert(datetime,'31/12/2007',103) ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'Prueba' , 3 , 1 , dateadd(dd,0, datediff(dd,0,getdate())) , dateadd(dd,0, datediff(dd,0,getdate())) ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 'prueba' , 2 , 10 , dateadd(dd,0, datediff(dd,0,getdate())) , dateadd(dd,0, datediff(dd,0,getdate())) ) "); ASGcondb.exeSelectSimple("select tabla99.campo2 from tabla99 "); ASGcondb.exeSelectSimple("select prueba1.campo2 from prueba1 "); ASGcondb.exeSelectSimple("select informix.tabla99.campo2 from tabla99 "); ASGcondb.exeSelectSimple("select informix.prueba1.campo2 from prueba1 "); ASGcondb.exeSelectSimple("select e.campo1 , f.campo1 , g.campo1 from prueba1 e , prueba2 f , tabla99 g "); Statement ASG_st1 = ASGcondb.retCon().createStatement();

Page 294: IfxToJava2

294 ResultSet ASG_r1 = ASG_st1.executeQuery("select campo3 + campo2 + 1 from prueba1 where campo2 = 1 "); try { ASG_r1.next(); tres = ASG_r1.getDouble(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("resultado sumar dos números: " + tres ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select campo4 + campo2 + 1 from prueba1 where campo2 = 1 "); try { ASG_r2.next(); fecha = ASG_r2.getDate(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("resultado sumar fecha y entero: " + ASGfaux.formato_fecha(fecha) ); dos = 2 ; Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select campo4 + "+ dos +" from prueba1 where campo2 = 1 "); try { ASG_r3.next(); fecha = ASG_r3.getDate(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("resultado sumar fecha y entero: " + ASGfaux.formato_fecha(fecha) ); Statement ASG_st4 = ASGcondb.retCon().createStatement(); ResultSet ASG_r4 = ASG_st4.executeQuery("select datediff(dd,campo4 ,convert(datetime,'31/12/2007',103) ) from prueba1 where campo2 = 1 "); try { ASG_r4.next(); dos = ASG_r4.getInt(1); } catch (SQLException e) {} ASG_r4.close(); ASG_st4.close(); System.out.println("resultado restar dos fechas: " + dos ); Statement ASG_st5 = ASGcondb.retCon().createStatement(); ResultSet ASG_r5 = ASG_st5.executeQuery("select datediff(dd,campo4 ,{d '"+ fecha +"'} ) from prueba1 where campo2 = 1 "); try { ASG_r5.next(); dos = ASG_r5.getInt(1); } catch (SQLException e) {} ASG_r5.close(); ASG_st5.close(); System.out.println("resultado restar dos fechas: " + dos ); ASGcondb.exeUpdate("insert into prueba1 values ( 'prueba' , 3 , 5 , {d '"+ fecha +"'} , dateadd(dd,0, datediff(dd,0,getdate())) ) "); Statement ASG_st6 = ASGcondb.retCon().createStatement(); ResultSet ASG_r6 = ASG_st6.executeQuery("select datediff(dd,campo4 ,{d '"+ fecha +"'} ) from prueba1 where campo2 = 2 "); try { ASG_r6.next(); dos = ASG_r6.getInt(1); } catch (SQLException e) {} ASG_r6.close(); ASG_st6.close(); System.out.println("resultado de restar dos fechas: " + dos ); Statement ASG_st7 = ASGcondb.retCon().createStatement(); ResultSet ASG_r7 = ASG_st7.executeQuery("select datediff(dd,campo4 ,campo5 ) from prueba1 where campo2 = 2 "); try { ASG_r7.next(); dos = ASG_r7.getInt(1); } catch (SQLException e) {} ASG_r7.close(); ASG_st7.close(); System.out.println("resultado de restar dos fechas: " + dos ); Statement ASG_st8 = ASGcondb.retCon().createStatement(); ResultSet ASG_r8 = ASG_st8.executeQuery("select datediff(dd,dateadd(dd,0, datediff(dd,0,getdate())) ,{d '"+ fecha +"'} ) from prueba1 where campo2 = 2 "); try { ASG_r8.next(); dos = ASG_r8.getInt(1); } catch (SQLException e) {} ASG_r8.close(); ASG_st8.close(); System.out.println("resultado de restar dos fechas: " + dos ); Statement ASG_st9 = ASGcondb.retCon().createStatement(); ResultSet ASG_r9 = ASG_st9.executeQuery("select campo4 from prueba1 where campo2 = 1 "); try { ASG_r9.next(); fecha2 = ASG_r9.getDate(1); } catch (SQLException e) {} ASG_r9.close(); ASG_st9.close(); System.out.println("fecha fila1: " + ASGfaux.formato_fecha(fecha2) ); Statement ASG_st10 = ASGcondb.retCon().createStatement(); ResultSet ASG_r10 = ASG_st10.executeQuery("select campo4 from prueba1 where campo2 = 2 ");

Page 295: IfxToJava2

295 try { ASG_r10.next(); fecha2 = ASG_r10.getDate(1); } catch (SQLException e) {} ASG_r10.close(); ASG_st10.close(); System.out.println("fecha fila2: " + ASGfaux.formato_fecha(fecha2) ); Statement ASG_st11 = ASGcondb.retCon().createStatement(); ResultSet ASG_r11 = ASG_st11.executeQuery("select campo4 from prueba1 where campo2 = 3 "); try { ASG_r11.next(); fecha2 = ASG_r11.getDate(1); } catch (SQLException e) {} ASG_r11.close(); ASG_st11.close(); System.out.println("fecha fila3: " + ASGfaux.formato_fecha(fecha2) ); Statement ASG_st12 = ASGcondb.retCon().createStatement(); ResultSet ASG_r12 = ASG_st12.executeQuery("select count ( campo2 ) from prueba1 where campo4 < {d '"+ fecha +"'} "); try { ASG_r12.next(); dos = ASG_r12.getInt(1); } catch (SQLException e) {} ASG_r12.close(); ASG_st12.close(); System.out.println("número de filas con fecha menor que: " + ASGfaux.formato_fecha(fecha) + " = " + dos ); Statement ASG_st13 = ASGcondb.retCon().createStatement(); ResultSet ASG_r13 = ASG_st13.executeQuery("select count ( * ) from prueba1 where campo2 between 1 and 2 "); try { ASG_r13.next(); dos = ASG_r13.getInt(1); } catch (SQLException e) {} ASG_r13.close(); ASG_st13.close(); System.out.println("número de filas con campo2 entre 1 y 2: " + dos ); Statement ASG_st14 = ASGcondb.retCon().createStatement(); ResultSet ASG_r14 = ASG_st14.executeQuery("select campo3 from prueba1 where exists ( select campo2 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r14.next(); tres = ASG_r14.getDouble(1); } catch (SQLException e) {} ASG_r14.close(); ASG_st14.close(); System.out.println("resultado exist: " + tres ); Statement ASG_st15 = ASGcondb.retCon().createStatement(); ResultSet ASG_r15 = ASG_st15.executeQuery("select campo3 from prueba1 where campo2 in ( select campo4 from prueba2 ) "); try { ASG_r15.next(); tres = ASG_r15.getDouble(1); } catch (SQLException e) {} ASG_r15.close(); ASG_st15.close(); System.out.println("resultado in: " + tres ); Statement ASG_st16 = ASGcondb.retCon().createStatement(); ResultSet ASG_r16 = ASG_st16.executeQuery("select sum ( campo3 ) from prueba1 where campo2 in ( 1 , 2 , 3 , 4 , 6 ) "); try { ASG_r16.next(); tres = ASG_r16.getDouble(1); } catch (SQLException e) {} ASG_r16.close(); ASG_st16.close(); System.out.println("resultado in: " + tres ); Statement ASG_st17 = ASGcondb.retCon().createStatement(); ResultSet ASG_r17 = ASG_st17.executeQuery("select sum ( campo3 ) from prueba1 where campo2 not in ( select campo4 from prueba2 ) "); try { ASG_r17.next(); tres = ASG_r17.getDouble(1); } catch (SQLException e) {} ASG_r17.close(); ASG_st17.close(); System.out.println("resultado not in: " + tres ); Statement ASG_st18 = ASGcondb.retCon().createStatement(); ResultSet ASG_r18 = ASG_st18.executeQuery("select count ( * ) from prueba1 where campo1 is null "); try { ASG_r18.next(); dos = ASG_r18.getInt(1); } catch (SQLException e) {} ASG_r18.close(); ASG_st18.close(); System.out.println("filas con valores nulos: " + dos ); Statement ASG_st19 = ASGcondb.retCon().createStatement(); ResultSet ASG_r19 = ASG_st19.executeQuery("select count ( * ) from prueba1 where campo1 is not null "); try { ASG_r19.next(); dos = ASG_r19.getInt(1); }

Page 296: IfxToJava2

296 catch (SQLException e) {} ASG_r19.close(); ASG_st19.close(); System.out.println("filas con valores no nulos: " + dos ); Statement ASG_st20 = ASGcondb.retCon().createStatement(); ResultSet ASG_r20 = ASG_st20.executeQuery("select sum ( campo3 ) from prueba1 where campo2 > any ( select campo4 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r20.next(); tres = ASG_r20.getDouble(1); } catch (SQLException e) {} ASG_r20.close(); ASG_st20.close(); System.out.println("resultado any: " + tres ); Statement ASG_st21 = ASGcondb.retCon().createStatement(); ResultSet ASG_r21 = ASG_st21.executeQuery("select sum ( campo3 ) from prueba1 where campo2 >= some ( select campo4 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r21.next(); tres = ASG_r21.getDouble(1); } catch (SQLException e) {} ASG_r21.close(); ASG_st21.close(); System.out.println("resultado some: " + tres ); Statement ASG_st22 = ASGcondb.retCon().createStatement(); ResultSet ASG_r22 = ASG_st22.executeQuery("select sum ( campo3 ) from prueba1 where campo2 > all ( select campo4 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r22.next(); tres = ASG_r22.getDouble(1); } catch (SQLException e) {} ASG_r22.close(); ASG_st22.close(); System.out.println("resultado all: " + tres ); Statement ASG_st23 = ASGcondb.retCon().createStatement(); ResultSet ASG_r23 = ASG_st23.executeQuery("select count ( campo2 ) from prueba1 where campo1 like 'P%' escape '$' "); try { ASG_r23.next(); dos = ASG_r23.getInt(1); } catch (SQLException e) {} ASG_r23.close(); ASG_st23.close(); System.out.println("filas que cumplen la condicion matches P* escape $ : " + dos ); Statement ASG_st24 = ASGcondb.retCon().createStatement(); ResultSet ASG_r24 = ASG_st24.executeQuery("select count ( * ) from prueba1 where campo1 not like 'P%' escape '\\' "); try { ASG_r24.next(); dos = ASG_r24.getInt(1); } catch (SQLException e) {} ASG_r24.close(); ASG_st24.close(); System.out.println("filas que cumplen la condicion not like P% : " + dos ); Statement ASG_st25 = ASGcondb.retCon().createStatement(); ResultSet ASG_r25 = ASG_st25.executeQuery("select count ( * ) from prueba1 where campo1 not like '_rueba' escape '\\' "); try { ASG_r25.next(); dos = ASG_r25.getInt(1); } catch (SQLException e) {} ASG_r25.close(); ASG_st25.close(); System.out.println("filas que cumplen la condicion not like _rueba : " + dos ); Statement ASG_st26 = ASGcondb.retCon().createStatement(); ResultSet ASG_r26 = ASG_st26.executeQuery("select count ( * ) from prueba1 where campo1 like '_[a-z]ueba' escape '\\' "); try { ASG_r26.next(); dos = ASG_r26.getInt(1); } catch (SQLException e) {} ASG_r26.close(); ASG_st26.close(); System.out.println("filas que cumplen la condicion matches ?[a-z]ueba : " + dos ); Statement ASG_st27 = ASGcondb.retCon().createStatement(); ResultSet ASG_r27 = ASG_st27.executeQuery("select count ( * ) from prueba1 where campo1 like '_[^r-s]ueba' escape '\\' "); try { ASG_r27.next(); dos = ASG_r27.getInt(1); } catch (SQLException e) {} ASG_r27.close(); ASG_st27.close(); System.out.println("filas que cumplen la condicion matches ?[^r-s]ueba : " + dos ); Statement ASG_st28 = ASGcondb.retCon().createStatement(); ResultSet ASG_r28 = ASG_st28.executeQuery("select count ( * ) from prueba1 where campo1 like '_[rs]ueba' escape '\\' "); try { ASG_r28.next(); dos = ASG_r28.getInt(1); } catch (SQLException e) {}

Page 297: IfxToJava2

297 ASG_r28.close(); ASG_st28.close(); System.out.println("filas que cumplen la condicion matches ?[rs]ueba : " + dos ); Statement ASG_st29 = ASGcondb.retCon().createStatement(); ResultSet ASG_r29 = ASG_st29.executeQuery("select count ( * ) from prueba1 where campo1 like '_[^rs]ueba' escape '\\' "); try { ASG_r29.next(); dos = ASG_r29.getInt(1); } catch (SQLException e) {} ASG_r29.close(); ASG_st29.close(); System.out.println("filas que cumplen la condicion matches ?[^rs]ueba : " + dos ); Statement ASG_st30 = ASGcondb.retCon().createStatement(); ResultSet ASG_r30 = ASG_st30.executeQuery("select count ( * ) from prueba1 where campo1 like '_[a-z123456789A-Z]ueba' escape '\\' "); try { ASG_r30.next(); dos = ASG_r30.getInt(1); } catch (SQLException e) {} ASG_r30.close(); ASG_st30.close(); System.out.println("filas que cumplen la condicion matches ?[a-z123456789A-Z]ueba : " + dos ); Statement ASG_st31 = ASGcondb.retCon().createStatement(); ResultSet ASG_r31 = ASG_st31.executeQuery("select count ( * ) from prueba1 where campo1 like '_[a-zA-Z123456789]ueba' escape '\\' "); try { ASG_r31.next(); dos = ASG_r31.getInt(1); } catch (SQLException e) {} ASG_r31.close(); ASG_st31.close(); System.out.println("filas que cumplen la condicion matches ?[a-zA-Z123456789]ueba : " + dos ); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class opersql { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; int dos ; double tres ; java.sql.Date fecha , fecha2 ; fecha2 = null; fecha = null; uno = ""; dos = 0; tres = 0.0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 cascade constraints"); ASGcondb.exeUpdate("drop table prueba2 cascade constraints"); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 smallint , campo3 decimal(10,2) , campo4 date , campo5 date ) "); ASGcondb.exeUpdate("create table prueba2 ( campo5 char(20) , campo4 smallint , campo1 decimal(10,2) , campo2 date , campo3 date ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'prueba' , 1 , 8.2 , to_date(to_char(sysdate,'dd/mm/yyyy')) , to_date('31/12/2007','dd/mm/yyyy') ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'otra Cosa' , 2 , 3 , to_date(to_char(sysdate,'dd/mm/yyyy')) , to_date('31/12/2007','dd/mm/yyyy') ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'Prueba' , 3 , 1 , to_date(to_char(sysdate,'dd/mm/yyyy')) , to_date(to_char(sysdate,'dd/mm/yyyy')) ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 'prueba' , 2 , 10 , to_date(to_char(sysdate,'dd/mm/yyyy')) , to_date(to_char(sysdate,'dd/mm/yyyy')) ) "); ASGcondb.exeSelectSimple("select tabla99.campo2 from tabla99 "); ASGcondb.exeSelectSimple("select prueba1.campo2 from prueba1 "); ASGcondb.exeSelectSimple("select informix.tabla99.campo2 from informix.tabla99 "); ASGcondb.exeSelectSimple("select informix.prueba1.campo2 from informix.prueba1 "); ASGcondb.exeSelectSimple("select e.campo1 , f.campo1 , g.campo1 from prueba1 e , prueba2 f , tabla99 g "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select campo3 + campo2 + 1 from prueba1 where campo2 = 1 "); try { ASG_r1.next(); tres = ASG_r1.getDouble(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("resultado sumar dos números: " + tres ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select campo4 + campo2 + 1 from prueba1 where campo2 = 1 "); try { ASG_r2.next(); fecha = ASG_r2.getDate(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close();

Page 298: IfxToJava2

298 System.out.println("resultado sumar fecha y entero: " + ASGfaux.formato_fecha(fecha) ); dos = 2 ; Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select campo4 + "+ dos +" from prueba1 where campo2 = 1 "); try { ASG_r3.next(); fecha = ASG_r3.getDate(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("resultado sumar fecha y entero: " + ASGfaux.formato_fecha(fecha) ); Statement ASG_st4 = ASGcondb.retCon().createStatement(); ResultSet ASG_r4 = ASG_st4.executeQuery("select to_date('31/12/2007','dd/mm/yyyy') - campo4 from prueba1 where campo2 = 1 "); try { ASG_r4.next(); dos = ASG_r4.getInt(1); } catch (SQLException e) {} ASG_r4.close(); ASG_st4.close(); System.out.println("resultado restar dos fechas: " + dos ); Statement ASG_st5 = ASGcondb.retCon().createStatement(); ResultSet ASG_r5 = ASG_st5.executeQuery("select {d '"+ fecha +"'} - campo4 from prueba1 where campo2 = 1 "); try { ASG_r5.next(); dos = ASG_r5.getInt(1); } catch (SQLException e) {} ASG_r5.close(); ASG_st5.close(); System.out.println("resultado restar dos fechas: " + dos ); ASGcondb.exeUpdate("insert into prueba1 values ( 'prueba' , 3 , 5 , {d '"+ fecha +"'} , to_date(to_char(sysdate,'dd/mm/yyyy')) ) "); Statement ASG_st6 = ASGcondb.retCon().createStatement(); ResultSet ASG_r6 = ASG_st6.executeQuery("select {d '"+ fecha +"'} - campo4 from prueba1 where campo2 = 2 "); try { ASG_r6.next(); dos = ASG_r6.getInt(1); } catch (SQLException e) {} ASG_r6.close(); ASG_st6.close(); System.out.println("resultado de restar dos fechas: " + dos ); Statement ASG_st7 = ASGcondb.retCon().createStatement(); ResultSet ASG_r7 = ASG_st7.executeQuery("select campo5 - campo4 from prueba1 where campo2 = 2 "); try { ASG_r7.next(); dos = ASG_r7.getInt(1); } catch (SQLException e) {} ASG_r7.close(); ASG_st7.close(); System.out.println("resultado de restar dos fechas: " + dos ); Statement ASG_st8 = ASGcondb.retCon().createStatement(); ResultSet ASG_r8 = ASG_st8.executeQuery("select {d '"+ fecha +"'} - to_date(to_char(sysdate,'dd/mm/yyyy')) from prueba1 where campo2 = 2 "); try { ASG_r8.next(); dos = ASG_r8.getInt(1); } catch (SQLException e) {} ASG_r8.close(); ASG_st8.close(); System.out.println("resultado de restar dos fechas: " + dos ); Statement ASG_st9 = ASGcondb.retCon().createStatement(); ResultSet ASG_r9 = ASG_st9.executeQuery("select campo4 from prueba1 where campo2 = 1 "); try { ASG_r9.next(); fecha2 = ASG_r9.getDate(1); } catch (SQLException e) {} ASG_r9.close(); ASG_st9.close(); System.out.println("fecha fila1: " + ASGfaux.formato_fecha(fecha2) ); Statement ASG_st10 = ASGcondb.retCon().createStatement(); ResultSet ASG_r10 = ASG_st10.executeQuery("select campo4 from prueba1 where campo2 = 2 "); try { ASG_r10.next(); fecha2 = ASG_r10.getDate(1); } catch (SQLException e) {} ASG_r10.close(); ASG_st10.close(); System.out.println("fecha fila2: " + ASGfaux.formato_fecha(fecha2) ); Statement ASG_st11 = ASGcondb.retCon().createStatement(); ResultSet ASG_r11 = ASG_st11.executeQuery("select campo4 from prueba1 where campo2 = 3 "); try { ASG_r11.next(); fecha2 = ASG_r11.getDate(1); } catch (SQLException e) {} ASG_r11.close(); ASG_st11.close(); System.out.println("fecha fila3: " + ASGfaux.formato_fecha(fecha2) ); Statement ASG_st12 = ASGcondb.retCon().createStatement();

Page 299: IfxToJava2

299 ResultSet ASG_r12 = ASG_st12.executeQuery("select count ( campo2 ) from prueba1 where campo4 < {d '"+ fecha +"'} "); try { ASG_r12.next(); dos = ASG_r12.getInt(1); } catch (SQLException e) {} ASG_r12.close(); ASG_st12.close(); System.out.println("número de filas con fecha menor que: " + ASGfaux.formato_fecha(fecha) + " = " + dos ); Statement ASG_st13 = ASGcondb.retCon().createStatement(); ResultSet ASG_r13 = ASG_st13.executeQuery("select count ( * ) from prueba1 where campo2 between 1 and 2 "); try { ASG_r13.next(); dos = ASG_r13.getInt(1); } catch (SQLException e) {} ASG_r13.close(); ASG_st13.close(); System.out.println("número de filas con campo2 entre 1 y 2: " + dos ); Statement ASG_st14 = ASGcondb.retCon().createStatement(); ResultSet ASG_r14 = ASG_st14.executeQuery("select campo3 from prueba1 where exists ( select campo2 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r14.next(); tres = ASG_r14.getDouble(1); } catch (SQLException e) {} ASG_r14.close(); ASG_st14.close(); System.out.println("resultado exist: " + tres ); Statement ASG_st15 = ASGcondb.retCon().createStatement(); ResultSet ASG_r15 = ASG_st15.executeQuery("select campo3 from prueba1 where campo2 in ( select campo4 from prueba2 ) "); try { ASG_r15.next(); tres = ASG_r15.getDouble(1); } catch (SQLException e) {} ASG_r15.close(); ASG_st15.close(); System.out.println("resultado in: " + tres ); Statement ASG_st16 = ASGcondb.retCon().createStatement(); ResultSet ASG_r16 = ASG_st16.executeQuery("select sum ( campo3 ) from prueba1 where campo2 in ( 1 , 2 , 3 , 4 , 6 ) "); try { ASG_r16.next(); tres = ASG_r16.getDouble(1); } catch (SQLException e) {} ASG_r16.close(); ASG_st16.close(); System.out.println("resultado in: " + tres ); Statement ASG_st17 = ASGcondb.retCon().createStatement(); ResultSet ASG_r17 = ASG_st17.executeQuery("select sum ( campo3 ) from prueba1 where campo2 not in ( select campo4 from prueba2 ) "); try { ASG_r17.next(); tres = ASG_r17.getDouble(1); } catch (SQLException e) {} ASG_r17.close(); ASG_st17.close(); System.out.println("resultado not in: " + tres ); Statement ASG_st18 = ASGcondb.retCon().createStatement(); ResultSet ASG_r18 = ASG_st18.executeQuery("select count ( * ) from prueba1 where campo1 is null "); try { ASG_r18.next(); dos = ASG_r18.getInt(1); } catch (SQLException e) {} ASG_r18.close(); ASG_st18.close(); System.out.println("filas con valores nulos: " + dos ); Statement ASG_st19 = ASGcondb.retCon().createStatement(); ResultSet ASG_r19 = ASG_st19.executeQuery("select count ( * ) from prueba1 where campo1 is not null "); try { ASG_r19.next(); dos = ASG_r19.getInt(1); } catch (SQLException e) {} ASG_r19.close(); ASG_st19.close(); System.out.println("filas con valores no nulos: " + dos ); Statement ASG_st20 = ASGcondb.retCon().createStatement(); ResultSet ASG_r20 = ASG_st20.executeQuery("select sum ( campo3 ) from prueba1 where campo2 > any ( select campo4 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r20.next(); tres = ASG_r20.getDouble(1); } catch (SQLException e) {} ASG_r20.close(); ASG_st20.close(); System.out.println("resultado any: " + tres ); Statement ASG_st21 = ASGcondb.retCon().createStatement(); ResultSet ASG_r21 = ASG_st21.executeQuery("select sum ( campo3 ) from prueba1 where campo2 >= some ( select campo4 from prueba2 where campo4 = prueba1.campo2 ) "); try {

Page 300: IfxToJava2

300 ASG_r21.next(); tres = ASG_r21.getDouble(1); } catch (SQLException e) {} ASG_r21.close(); ASG_st21.close(); System.out.println("resultado some: " + tres ); Statement ASG_st22 = ASGcondb.retCon().createStatement(); ResultSet ASG_r22 = ASG_st22.executeQuery("select sum ( campo3 ) from prueba1 where campo2 > all ( select campo4 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r22.next(); tres = ASG_r22.getDouble(1); } catch (SQLException e) {} ASG_r22.close(); ASG_st22.close(); System.out.println("resultado all: " + tres ); Statement ASG_st23 = ASGcondb.retCon().createStatement(); ResultSet ASG_r23 = ASG_st23.executeQuery("select count ( campo2 ) from prueba1 where campo1 like 'P%' escape '$' "); try { ASG_r23.next(); dos = ASG_r23.getInt(1); } catch (SQLException e) {} ASG_r23.close(); ASG_st23.close(); System.out.println("filas que cumplen la condicion matches P* escape $ : " + dos ); Statement ASG_st24 = ASGcondb.retCon().createStatement(); ResultSet ASG_r24 = ASG_st24.executeQuery("select count ( * ) from prueba1 where campo1 not like 'P%' escape '\\' "); try { ASG_r24.next(); dos = ASG_r24.getInt(1); } catch (SQLException e) {} ASG_r24.close(); ASG_st24.close(); System.out.println("filas que cumplen la condicion not like P% : " + dos ); Statement ASG_st25 = ASGcondb.retCon().createStatement(); ResultSet ASG_r25 = ASG_st25.executeQuery("select count ( * ) from prueba1 where campo1 not like '_rueba%' escape '\\' "); try { ASG_r25.next(); dos = ASG_r25.getInt(1); } catch (SQLException e) {} ASG_r25.close(); ASG_st25.close(); System.out.println("filas que cumplen la condicion not like _rueba : " + dos ); Statement ASG_st26 = ASGcondb.retCon().createStatement(); ResultSet ASG_r26 = ASG_st26.executeQuery("select count ( * ) from prueba1 where campo1 like '__ueba%' escape '\\' and substr(campo1,2,1) in ('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z') "); try { ASG_r26.next(); dos = ASG_r26.getInt(1); } catch (SQLException e) {} ASG_r26.close(); ASG_st26.close(); System.out.println("filas que cumplen la condicion matches ?[a-z]ueba : " + dos ); Statement ASG_st27 = ASGcondb.retCon().createStatement(); ResultSet ASG_r27 = ASG_st27.executeQuery("select count ( * ) from prueba1 where campo1 like '__ueba%' escape '\\' and substr(campo1,2,1) not in ('r','s') "); try { ASG_r27.next(); dos = ASG_r27.getInt(1); } catch (SQLException e) {} ASG_r27.close(); ASG_st27.close(); System.out.println("filas que cumplen la condicion matches ?[^r-s]ueba : " + dos ); Statement ASG_st28 = ASGcondb.retCon().createStatement(); ResultSet ASG_r28 = ASG_st28.executeQuery("select count ( * ) from prueba1 where campo1 like '__ueba%' escape '\\' and substr(campo1,2,1) in ('r','s') "); try { ASG_r28.next(); dos = ASG_r28.getInt(1); } catch (SQLException e) {} ASG_r28.close(); ASG_st28.close(); System.out.println("filas que cumplen la condicion matches ?[rs]ueba : " + dos ); Statement ASG_st29 = ASGcondb.retCon().createStatement(); ResultSet ASG_r29 = ASG_st29.executeQuery("select count ( * ) from prueba1 where campo1 like '__ueba%' escape '\\' and substr(campo1,2,1) not in ('r','s') "); try { ASG_r29.next(); dos = ASG_r29.getInt(1); } catch (SQLException e) {} ASG_r29.close(); ASG_st29.close(); System.out.println("filas que cumplen la condicion matches ?[^rs]ueba : " + dos ); Statement ASG_st30 = ASGcondb.retCon().createStatement(); ResultSet ASG_r30 = ASG_st30.executeQuery("select count ( * ) from prueba1 where campo1 like '__ueba%' escape '\\' and substr(campo1,2,1) in ('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8') ");

Page 301: IfxToJava2

301 try { ASG_r30.next(); dos = ASG_r30.getInt(1); } catch (SQLException e) {} ASG_r30.close(); ASG_st30.close(); System.out.println("filas que cumplen la condicion matches ?[a-z123456789A-Z]ueba : " + dos ); Statement ASG_st31 = ASGcondb.retCon().createStatement(); ResultSet ASG_r31 = ASG_st31.executeQuery("select count ( * ) from prueba1 where campo1 like '__ueba%' escape '\\' and substr(campo1,2,1) in ('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9') "); try { ASG_r31.next(); dos = ASG_r31.getInt(1); } catch (SQLException e) {} ASG_r31.close(); ASG_st31.close(); System.out.println("filas que cumplen la condicion matches ?[a-zA-Z123456789]ueba : " + dos ); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class opersql { static String hola ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; int dos ; double tres ; java.sql.Date fecha , fecha2 ; fecha2 = null; fecha = null; uno = ""; dos = 0; tres = 0.0; ASGcondb.activaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.exeUpdate("drop table prueba2 "); ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 char(20) , campo2 smallint , campo3 decimal(10,2) , campo4 date , campo5 date ) "); ASGcondb.exeUpdate("create table prueba2 ( campo5 char(20) , campo4 smallint , campo1 decimal(10,2) , campo2 date , campo3 date ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'prueba' , 1 , 8.2 , current date , date('31/12/2007') ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'otra Cosa' , 2 , 3 , current date , date('31/12/2007') ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 'Prueba' , 3 , 1 , current date , current date ) "); ASGcondb.exeUpdate("insert into prueba2 values ( 'prueba' , 2 , 10 , current date , current date ) "); ASGcondb.exeSelectSimple("select tabla99.campo2 from tabla99 "); ASGcondb.exeSelectSimple("select prueba1.campo2 from prueba1 "); ASGcondb.exeSelectSimple("select informix.tabla99.campo2 from tabla99 "); ASGcondb.exeSelectSimple("select informix.prueba1.campo2 from prueba1 "); ASGcondb.exeSelectSimple("select e.campo1 , f.campo1 , g.campo1 from prueba1 e , prueba2 f , tabla99 g "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select campo3 + campo2 + 1 from prueba1 where campo2 = 1 "); try { ASG_r1.next(); tres = ASG_r1.getDouble(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println("resultado sumar dos números: " + tres ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select campo4 + campo2 DAY + 1 DAY from prueba1 where campo2 = 1 "); try { ASG_r2.next(); fecha = ASG_r2.getDate(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println("resultado sumar fecha y entero: " + ASGfaux.formato_fecha(fecha) ); dos = 2 ; Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select campo4 + "+ dos +" DAY from prueba1 where campo2 = 1 "); try { ASG_r3.next(); fecha = ASG_r3.getDate(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println("resultado sumar fecha y entero: " + ASGfaux.formato_fecha(fecha) ); Statement ASG_st4 = ASGcondb.retCon().createStatement(); ResultSet ASG_r4 = ASG_st4.executeQuery("select days(date('31/12/2007') ) - days(campo4 ) from prueba1 where campo2 = 1 "); try { ASG_r4.next();

Page 302: IfxToJava2

302 dos = ASG_r4.getInt(1); } catch (SQLException e) {} ASG_r4.close(); ASG_st4.close(); System.out.println("resultado restar dos fechas: " + dos ); Statement ASG_st5 = ASGcondb.retCon().createStatement(); ResultSet ASG_r5 = ASG_st5.executeQuery("select days({d '"+ fecha +"'} ) - days(campo4 ) from prueba1 where campo2 = 1 "); try { ASG_r5.next(); dos = ASG_r5.getInt(1); } catch (SQLException e) {} ASG_r5.close(); ASG_st5.close(); System.out.println("resultado restar dos fechas: " + dos ); ASGcondb.exeUpdate("insert into prueba1 values ( 'prueba' , 3 , 5 , {d '"+ fecha +"'} , current date ) "); Statement ASG_st6 = ASGcondb.retCon().createStatement(); ResultSet ASG_r6 = ASG_st6.executeQuery("select days({d '"+ fecha +"'} ) - days(campo4 ) from prueba1 where campo2 = 2 "); try { ASG_r6.next(); dos = ASG_r6.getInt(1); } catch (SQLException e) {} ASG_r6.close(); ASG_st6.close(); System.out.println("resultado de restar dos fechas: " + dos ); Statement ASG_st7 = ASGcondb.retCon().createStatement(); ResultSet ASG_r7 = ASG_st7.executeQuery("select days(campo5 ) - days(campo4 ) from prueba1 where campo2 = 2 "); try { ASG_r7.next(); dos = ASG_r7.getInt(1); } catch (SQLException e) {} ASG_r7.close(); ASG_st7.close(); System.out.println("resultado de restar dos fechas: " + dos ); Statement ASG_st8 = ASGcondb.retCon().createStatement(); ResultSet ASG_r8 = ASG_st8.executeQuery("select days({d '"+ fecha +"'} ) - days(current date ) from prueba1 where campo2 = 2 "); try { ASG_r8.next(); dos = ASG_r8.getInt(1); } catch (SQLException e) {} ASG_r8.close(); ASG_st8.close(); System.out.println("resultado de restar dos fechas: " + dos ); Statement ASG_st9 = ASGcondb.retCon().createStatement(); ResultSet ASG_r9 = ASG_st9.executeQuery("select campo4 from prueba1 where campo2 = 1 "); try { ASG_r9.next(); fecha2 = ASG_r9.getDate(1); } catch (SQLException e) {} ASG_r9.close(); ASG_st9.close(); System.out.println("fecha fila1: " + ASGfaux.formato_fecha(fecha2) ); Statement ASG_st10 = ASGcondb.retCon().createStatement(); ResultSet ASG_r10 = ASG_st10.executeQuery("select campo4 from prueba1 where campo2 = 2 "); try { ASG_r10.next(); fecha2 = ASG_r10.getDate(1); } catch (SQLException e) {} ASG_r10.close(); ASG_st10.close(); System.out.println("fecha fila2: " + ASGfaux.formato_fecha(fecha2) ); Statement ASG_st11 = ASGcondb.retCon().createStatement(); ResultSet ASG_r11 = ASG_st11.executeQuery("select campo4 from prueba1 where campo2 = 3 "); try { ASG_r11.next(); fecha2 = ASG_r11.getDate(1); } catch (SQLException e) {} ASG_r11.close(); ASG_st11.close(); System.out.println("fecha fila3: " + ASGfaux.formato_fecha(fecha2) ); Statement ASG_st12 = ASGcondb.retCon().createStatement(); ResultSet ASG_r12 = ASG_st12.executeQuery("select count ( campo2 ) from prueba1 where campo4 < {d '"+ fecha +"'} "); try { ASG_r12.next(); dos = ASG_r12.getInt(1); } catch (SQLException e) {} ASG_r12.close(); ASG_st12.close(); System.out.println("número de filas con fecha menor que: " + ASGfaux.formato_fecha(fecha) + " = " + dos ); Statement ASG_st13 = ASGcondb.retCon().createStatement(); ResultSet ASG_r13 = ASG_st13.executeQuery("select count ( * ) from prueba1 where campo2 between 1 and 2 "); try { ASG_r13.next(); dos = ASG_r13.getInt(1); } catch (SQLException e) {} ASG_r13.close();

Page 303: IfxToJava2

303 ASG_st13.close(); System.out.println("número de filas con campo2 entre 1 y 2: " + dos ); Statement ASG_st14 = ASGcondb.retCon().createStatement(); ResultSet ASG_r14 = ASG_st14.executeQuery("select campo3 from prueba1 where exists ( select campo2 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r14.next(); tres = ASG_r14.getDouble(1); } catch (SQLException e) {} ASG_r14.close(); ASG_st14.close(); System.out.println("resultado exist: " + tres ); Statement ASG_st15 = ASGcondb.retCon().createStatement(); ResultSet ASG_r15 = ASG_st15.executeQuery("select campo3 from prueba1 where campo2 in ( select campo4 from prueba2 ) "); try { ASG_r15.next(); tres = ASG_r15.getDouble(1); } catch (SQLException e) {} ASG_r15.close(); ASG_st15.close(); System.out.println("resultado in: " + tres ); Statement ASG_st16 = ASGcondb.retCon().createStatement(); ResultSet ASG_r16 = ASG_st16.executeQuery("select sum ( campo3 ) from prueba1 where campo2 in ( 1 , 2 , 3 , 4 , 6 ) "); try { ASG_r16.next(); tres = ASG_r16.getDouble(1); } catch (SQLException e) {} ASG_r16.close(); ASG_st16.close(); System.out.println("resultado in: " + tres ); Statement ASG_st17 = ASGcondb.retCon().createStatement(); ResultSet ASG_r17 = ASG_st17.executeQuery("select sum ( campo3 ) from prueba1 where campo2 not in ( select campo4 from prueba2 ) "); try { ASG_r17.next(); tres = ASG_r17.getDouble(1); } catch (SQLException e) {} ASG_r17.close(); ASG_st17.close(); System.out.println("resultado not in: " + tres ); Statement ASG_st18 = ASGcondb.retCon().createStatement(); ResultSet ASG_r18 = ASG_st18.executeQuery("select count ( * ) from prueba1 where campo1 is null "); try { ASG_r18.next(); dos = ASG_r18.getInt(1); } catch (SQLException e) {} ASG_r18.close(); ASG_st18.close(); System.out.println("filas con valores nulos: " + dos ); Statement ASG_st19 = ASGcondb.retCon().createStatement(); ResultSet ASG_r19 = ASG_st19.executeQuery("select count ( * ) from prueba1 where campo1 is not null "); try { ASG_r19.next(); dos = ASG_r19.getInt(1); } catch (SQLException e) {} ASG_r19.close(); ASG_st19.close(); System.out.println("filas con valores no nulos: " + dos ); Statement ASG_st20 = ASGcondb.retCon().createStatement(); ResultSet ASG_r20 = ASG_st20.executeQuery("select sum ( campo3 ) from prueba1 where campo2 > any ( select campo4 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r20.next(); tres = ASG_r20.getDouble(1); } catch (SQLException e) {} ASG_r20.close(); ASG_st20.close(); System.out.println("resultado any: " + tres ); Statement ASG_st21 = ASGcondb.retCon().createStatement(); ResultSet ASG_r21 = ASG_st21.executeQuery("select sum ( campo3 ) from prueba1 where campo2 >= some ( select campo4 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r21.next(); tres = ASG_r21.getDouble(1); } catch (SQLException e) {} ASG_r21.close(); ASG_st21.close(); System.out.println("resultado some: " + tres ); Statement ASG_st22 = ASGcondb.retCon().createStatement(); ResultSet ASG_r22 = ASG_st22.executeQuery("select sum ( campo3 ) from prueba1 where campo2 > all ( select campo4 from prueba2 where campo4 = prueba1.campo2 ) "); try { ASG_r22.next(); tres = ASG_r22.getDouble(1); } catch (SQLException e) {} ASG_r22.close(); ASG_st22.close(); System.out.println("resultado all: " + tres ); Statement ASG_st23 = ASGcondb.retCon().createStatement();

Page 304: IfxToJava2

304 ResultSet ASG_r23 = ASG_st23.executeQuery("select count ( campo2 ) from prueba1 where campo1 like 'P%' escape '$' "); try { ASG_r23.next(); dos = ASG_r23.getInt(1); } catch (SQLException e) {} ASG_r23.close(); ASG_st23.close(); System.out.println("filas que cumplen la condicion matches P* escape $ : " + dos ); Statement ASG_st24 = ASGcondb.retCon().createStatement(); ResultSet ASG_r24 = ASG_st24.executeQuery("select count ( * ) from prueba1 where campo1 not like 'P%' escape '\\' "); try { ASG_r24.next(); dos = ASG_r24.getInt(1); } catch (SQLException e) {} ASG_r24.close(); ASG_st24.close(); System.out.println("filas que cumplen la condicion not like P% : " + dos ); Statement ASG_st25 = ASGcondb.retCon().createStatement(); ResultSet ASG_r25 = ASG_st25.executeQuery("select count ( * ) from prueba1 where campo1 not like '_rueba%' escape '\\' "); try { ASG_r25.next(); dos = ASG_r25.getInt(1); } catch (SQLException e) {} ASG_r25.close(); ASG_st25.close(); System.out.println("filas que cumplen la condicion not like _rueba : " + dos ); Statement ASG_st26 = ASGcondb.retCon().createStatement(); ResultSet ASG_r26 = ASG_st26.executeQuery("select count ( * ) from prueba1 where campo1 like '__ueba%' escape '\\' and substr(campo1,2,1) in ('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z') "); try { ASG_r26.next(); dos = ASG_r26.getInt(1); } catch (SQLException e) {} ASG_r26.close(); ASG_st26.close(); System.out.println("filas que cumplen la condicion matches ?[a-z]ueba : " + dos ); Statement ASG_st27 = ASGcondb.retCon().createStatement(); ResultSet ASG_r27 = ASG_st27.executeQuery("select count ( * ) from prueba1 where campo1 like '__ueba%' escape '\\' and substr(campo1,2,1) not in ('r','s') "); try { ASG_r27.next(); dos = ASG_r27.getInt(1); } catch (SQLException e) {} ASG_r27.close(); ASG_st27.close(); System.out.println("filas que cumplen la condicion matches ?[^r-s]ueba : " + dos ); Statement ASG_st28 = ASGcondb.retCon().createStatement(); ResultSet ASG_r28 = ASG_st28.executeQuery("select count ( * ) from prueba1 where campo1 like '__ueba%' escape '\\' and substr(campo1,2,1) in ('r','s') "); try { ASG_r28.next(); dos = ASG_r28.getInt(1); } catch (SQLException e) {} ASG_r28.close(); ASG_st28.close(); System.out.println("filas que cumplen la condicion matches ?[rs]ueba : " + dos ); Statement ASG_st29 = ASGcondb.retCon().createStatement(); ResultSet ASG_r29 = ASG_st29.executeQuery("select count ( * ) from prueba1 where campo1 like '__ueba%' escape '\\' and substr(campo1,2,1) not in ('r','s') "); try { ASG_r29.next(); dos = ASG_r29.getInt(1); } catch (SQLException e) {} ASG_r29.close(); ASG_st29.close(); System.out.println("filas que cumplen la condicion matches ?[^rs]ueba : " + dos ); Statement ASG_st30 = ASGcondb.retCon().createStatement(); ResultSet ASG_r30 = ASG_st30.executeQuery("select count ( * ) from prueba1 where campo1 like '__ueba%' escape '\\' and substr(campo1,2,1) in ('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8') "); try { ASG_r30.next(); dos = ASG_r30.getInt(1); } catch (SQLException e) {} ASG_r30.close(); ASG_st30.close(); System.out.println("filas que cumplen la condicion matches ?[a-z123456789A-Z]ueba : " + dos ); Statement ASG_st31 = ASGcondb.retCon().createStatement(); ResultSet ASG_r31 = ASG_st31.executeQuery("select count ( * ) from prueba1 where campo1 like '__ueba%' escape '\\' and substr(campo1,2,1) in ('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9') "); try { ASG_r31.next(); dos = ASG_r31.getInt(1); } catch (SQLException e) {}

Page 305: IfxToJava2

305 ASG_r31.close(); ASG_st31.close(); System.out.println("filas que cumplen la condicion matches ?[a-zA-Z123456789]ueba : " + dos ); } }

EJEMPLO DE MANEJO DE CONSTANTES TIPO FECHA

CÓDIGO FUENTE INFORMIX-4GL: CTESFECHA.4GL #Expresiones SQL #expresion de manejo de constantes tipo fecha database datos define fecha date define fechahora datetime year to fraction main define uno char(20), dos date, tres datetime year to fraction, cuatro integer, cinco decimal(12,2) whenever error stop drop table prueba1 whenever error continue create table prueba1 ( campo1 integer, campo2 decimal(20,0), campo3 date, campo4 datetime year to fraction ) #ctes fecha número let dos = 1; message dos insert into prueba1 values (1,1,today,current); insert into prueba1 values (2,1,dos,current); let dos = date (39378) message dos let cuatro = 39378 let dos = date (cuatro) message dos insert into prueba1 values (3,40000,dos,current); select date(campo1) into fecha from prueba1 where campo1 = 3 message fecha select date(39379) into fecha from prueba1 where campo1 = 3 message fecha select count(campo1) into cuatro from prueba1 where campo3 > 39376 message cuatro select count(campo1) into cuatro from prueba1 where 39376 > campo3 message cuatro #ctes fecha cadena let dos = "01/01/1900"; message dos insert into prueba1 values (1,1,today,current); insert into prueba1 values (2,1,dos,current); let dos = date ("24/10/2007") message dos let dos = "24/10/2007" let dos = date (dos) message dos insert into prueba1 values (3,40000,dos,current); select date(campo1) into fecha from prueba1 where campo1 = 3 message fecha select date("25/10/2007") into fecha from prueba1 where campo1 = 3 message fecha select date(today) into fecha from prueba1 where campo1 = 3 message fecha select count(campo1) into cuatro from prueba1 where campo3 > "22/10/2007" message cuatro select count(campo1) into cuatro from prueba1 where "22/10/2007" > campo3 message cuatro #ctes fecha/hora cadena let tres = "1900-01-01 00:00:00" message tres insert into prueba1 values (1,1,today,current); insert into prueba1 values (2,1,today,tres); let tres = date ("2007-10-24 00:00:00") message tres let tres = "2007-10-24 00:00:00" let tres = date (tres) message tres

Page 306: IfxToJava2

306 insert into prueba1 values (3,40000,dos,tres); select date(campo3) into fechahora from prueba1 where campo1 = 3 message fechahora select date(current) into fechahora from prueba1 where campo1 = 3 message fechahora select count(campo1) into cuatro from prueba1 where campo4 > "2007-10-22 00:00:00.0" message cuatro select count(campo1) into cuatro from prueba1 where "2007-10-22 00:00:00.0" > campo4 message cuatro end main

CÓDIGO OBJETO: CTESFECHA.JAVA

CÓDIGO OBJETO INFORMIX import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class ctesfecha { static java.sql.Date fecha ; static java.sql.Timestamp fechahora ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; java.sql.Date dos ; java.sql.Timestamp tres ; int cuatro ; double cinco ; cuatro = 0; cinco = 0.0; uno = ""; dos = null; tres = null; ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 integer , campo2 decimal(20,0) , campo3 date , campo4 datetime year to fraction ) "); dos = ASGfaux.cteIntToFechaJ(1) ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 1 , 1 , today , current ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 2 , 1 , {d '"+ dos +"'} , current ) "); dos = ASGfaux.fecha( 39378 ) ; System.out.println(ASGfaux.formato_fecha(dos) ); cuatro = 39378 ; dos = ASGfaux.fecha( cuatro ) ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 3 , 40000 , {d '"+ dos +"'} , current ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select date( campo1 ) from prueba1 where campo1 = 3 "); try { ASG_r1.next(); fecha = ASG_r1.getDate(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select date( 39379 ) from prueba1 where campo1 = 3 "); try { ASG_r2.next(); fecha = ASG_r2.getDate(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select count ( campo1 ) from prueba1 where campo3 > 39376 "); try { ASG_r3.next(); cuatro = ASG_r3.getInt(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println(cuatro ); Statement ASG_st4 = ASGcondb.retCon().createStatement(); ResultSet ASG_r4 = ASG_st4.executeQuery("select count ( campo1 ) from prueba1 where 39376 > campo3 "); try { ASG_r4.next(); cuatro = ASG_r4.getInt(1); } catch (SQLException e) {} ASG_r4.close(); ASG_st4.close(); System.out.println(cuatro ); dos = ASGfaux.fecha("01/01/1900") ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 1 , 1 , today , current ) ");

Page 307: IfxToJava2

307 ASGcondb.exeUpdate("insert into prueba1 values ( 2 , 1 , {d '"+ dos +"'} , current ) "); dos = ASGfaux.fecha( ASGfaux.fecha("24/10/2007") ) ; System.out.println(ASGfaux.formato_fecha(dos) ); dos = ASGfaux.fecha("24/10/2007") ; dos = ASGfaux.fecha( dos ) ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 3 , 40000 , {d '"+ dos +"'} , current ) "); Statement ASG_st5 = ASGcondb.retCon().createStatement(); ResultSet ASG_r5 = ASG_st5.executeQuery("select date( campo1 ) from prueba1 where campo1 = 3 "); try { ASG_r5.next(); fecha = ASG_r5.getDate(1); } catch (SQLException e) {} ASG_r5.close(); ASG_st5.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st6 = ASGcondb.retCon().createStatement(); ResultSet ASG_r6 = ASG_st6.executeQuery("select date( '25/10/2007' ) from prueba1 where campo1 = 3 "); try { ASG_r6.next(); fecha = ASG_r6.getDate(1); } catch (SQLException e) {} ASG_r6.close(); ASG_st6.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st7 = ASGcondb.retCon().createStatement(); ResultSet ASG_r7 = ASG_st7.executeQuery("select date( today ) from prueba1 where campo1 = 3 "); try { ASG_r7.next(); fecha = ASG_r7.getDate(1); } catch (SQLException e) {} ASG_r7.close(); ASG_st7.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st8 = ASGcondb.retCon().createStatement(); ResultSet ASG_r8 = ASG_st8.executeQuery("select count ( campo1 ) from prueba1 where campo3 > '22/10/2007' "); try { ASG_r8.next(); cuatro = ASG_r8.getInt(1); } catch (SQLException e) {} ASG_r8.close(); ASG_st8.close(); System.out.println(cuatro ); Statement ASG_st9 = ASGcondb.retCon().createStatement(); ResultSet ASG_r9 = ASG_st9.executeQuery("select count ( campo1 ) from prueba1 where '22/10/2007' > campo3 "); try { ASG_r9.next(); cuatro = ASG_r9.getInt(1); } catch (SQLException e) {} ASG_r9.close(); ASG_st9.close(); System.out.println(cuatro ); tres = ASGfaux.fechahora("1900-01-01 00:00:00") ; System.out.println(tres ); ASGcondb.exeUpdate("insert into prueba1 values ( 1 , 1 , today , current ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 2 , 1 , today , {ts '"+ tres +"'} ) "); tres = ASGfaux.fecha( ASGfaux.fechahora("2007-10-24 00:00:00") ) ; System.out.println(tres ); tres = ASGfaux.fechahora("2007-10-24 00:00:00") ; tres = ASGfaux.fecha( tres ) ; System.out.println(tres ); ASGcondb.exeUpdate("insert into prueba1 values ( 3 , 40000 , {d '"+ dos +"'} , {ts '"+ tres +"'} ) "); Statement ASG_st10 = ASGcondb.retCon().createStatement(); ResultSet ASG_r10 = ASG_st10.executeQuery("select date( campo3 ) from prueba1 where campo1 = 3 "); try { ASG_r10.next(); fechahora = ASG_r10.getTimestamp(1); } catch (SQLException e) {} ASG_r10.close(); ASG_st10.close(); System.out.println(fechahora ); Statement ASG_st11 = ASGcondb.retCon().createStatement(); ResultSet ASG_r11 = ASG_st11.executeQuery("select date( current ) from prueba1 where campo1 = 3 "); try { ASG_r11.next(); fechahora = ASG_r11.getTimestamp(1); } catch (SQLException e) {} ASG_r11.close(); ASG_st11.close(); System.out.println(fechahora ); Statement ASG_st12 = ASGcondb.retCon().createStatement(); ResultSet ASG_r12 = ASG_st12.executeQuery("select count ( campo1 ) from prueba1 where campo4 > '2007-10-22 00:00:00.0' "); try { ASG_r12.next(); cuatro = ASG_r12.getInt(1); } catch (SQLException e) {} ASG_r12.close(); ASG_st12.close(); System.out.println(cuatro ); Statement ASG_st13 = ASGcondb.retCon().createStatement(); ResultSet ASG_r13 = ASG_st13.executeQuery("select count ( campo1 ) from prueba1 where '2007-10-22 00:00:00.0' > campo4 ");

Page 308: IfxToJava2

308 try { ASG_r13.next(); cuatro = ASG_r13.getInt(1); } catch (SQLException e) {} ASG_r13.close(); ASG_st13.close(); System.out.println(cuatro ); } }

CÓDIGO OBJETO SQLSERVER import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class ctesfecha { static java.sql.Date fecha ; static java.sql.Timestamp fechahora ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; java.sql.Date dos ; java.sql.Timestamp tres ; int cuatro ; double cinco ; cuatro = 0; cinco = 0.0; uno = ""; dos = null; tres = null; ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 integer , campo2 decimal(20,0) , campo3 datetime , campo4 datetime ) "); dos = ASGfaux.cteIntToFechaJ(1) ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 1 , 1 , dateadd(dd,0, datediff(dd,0,getdate())) , getdate() ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 2 , 1 , {d '"+ dos +"'} , getdate() ) "); dos = ASGfaux.fecha( 39378 ) ; System.out.println(ASGfaux.formato_fecha(dos) ); cuatro = 39378 ; dos = ASGfaux.fecha( cuatro ) ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 3 , 40000 , {d '"+ dos +"'} , getdate() ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select convert(datetime, convert(datetime, ( campo1 - 1) ,103) ,103) from prueba1 where campo1 = 3 "); try { ASG_r1.next(); fecha = ASG_r1.getDate(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select convert(datetime, convert(datetime, ( 39379 - 1) ,103) ,103) from prueba1 where campo1 = 3 "); try { ASG_r2.next(); fecha = ASG_r2.getDate(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select count ( campo1 ) from prueba1 where campo3 > convert(datetime, 39376 - 1,103) "); try { ASG_r3.next(); cuatro = ASG_r3.getInt(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println(cuatro ); Statement ASG_st4 = ASGcondb.retCon().createStatement(); ResultSet ASG_r4 = ASG_st4.executeQuery("select count ( campo1 ) from prueba1 where 39376 > convert(int ,campo3 ) + 1 "); try { ASG_r4.next(); cuatro = ASG_r4.getInt(1); } catch (SQLException e) {} ASG_r4.close(); ASG_st4.close(); System.out.println(cuatro ); dos = ASGfaux.fecha("01/01/1900") ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 1 , 1 , dateadd(dd,0, datediff(dd,0,getdate())) , getdate() ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 2 , 1 , {d '"+ dos +"'} , getdate() ) "); dos = ASGfaux.fecha( ASGfaux.fecha("24/10/2007") ) ; System.out.println(ASGfaux.formato_fecha(dos) ); dos = ASGfaux.fecha("24/10/2007") ; dos = ASGfaux.fecha( dos ) ;

Page 309: IfxToJava2

309 System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 3 , 40000 , {d '"+ dos +"'} , getdate() ) "); Statement ASG_st5 = ASGcondb.retCon().createStatement(); ResultSet ASG_r5 = ASG_st5.executeQuery("select convert(datetime, convert(datetime, ( campo1 - 1) ,103) ,103) from prueba1 where campo1 = 3 "); try { ASG_r5.next(); fecha = ASG_r5.getDate(1); } catch (SQLException e) {} ASG_r5.close(); ASG_st5.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st6 = ASGcondb.retCon().createStatement(); ResultSet ASG_r6 = ASG_st6.executeQuery("select convert(datetime, convert(datetime,'25/10/2007',103) ,103) from prueba1 where campo1 = 3 "); try { ASG_r6.next(); fecha = ASG_r6.getDate(1); } catch (SQLException e) {} ASG_r6.close(); ASG_st6.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st7 = ASGcondb.retCon().createStatement(); ResultSet ASG_r7 = ASG_st7.executeQuery("select convert(datetime, dateadd(dd,0, datediff(dd,0,getdate())) ,103) from prueba1 where campo1 = 3 "); try { ASG_r7.next(); fecha = ASG_r7.getDate(1); } catch (SQLException e) {} ASG_r7.close(); ASG_st7.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st8 = ASGcondb.retCon().createStatement(); ResultSet ASG_r8 = ASG_st8.executeQuery("select count ( campo1 ) from prueba1 where campo3 > convert(datetime,'22/10/2007',103) "); try { ASG_r8.next(); cuatro = ASG_r8.getInt(1); } catch (SQLException e) {} ASG_r8.close(); ASG_st8.close(); System.out.println(cuatro ); Statement ASG_st9 = ASGcondb.retCon().createStatement(); ResultSet ASG_r9 = ASG_st9.executeQuery("select count ( campo1 ) from prueba1 where convert(datetime,'22/10/2007',103) > campo3 "); try { ASG_r9.next(); cuatro = ASG_r9.getInt(1); } catch (SQLException e) {} ASG_r9.close(); ASG_st9.close(); System.out.println(cuatro ); tres = ASGfaux.fechahora("1900-01-01 00:00:00") ; System.out.println(tres ); ASGcondb.exeUpdate("insert into prueba1 values ( 1 , 1 , dateadd(dd,0, datediff(dd,0,getdate())) , getdate() ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 2 , 1 , dateadd(dd,0, datediff(dd,0,getdate())) , {ts '"+ tres +"'} ) "); tres = ASGfaux.fecha( ASGfaux.fechahora("2007-10-24 00:00:00") ) ; System.out.println(tres ); tres = ASGfaux.fechahora("2007-10-24 00:00:00") ; tres = ASGfaux.fecha( tres ) ; System.out.println(tres ); ASGcondb.exeUpdate("insert into prueba1 values ( 3 , 40000 , {d '"+ dos +"'} , {ts '"+ tres +"'} ) "); Statement ASG_st10 = ASGcondb.retCon().createStatement(); ResultSet ASG_r10 = ASG_st10.executeQuery("select convert(datetime, campo3 ,103) from prueba1 where campo1 = 3 "); try { ASG_r10.next(); fechahora = ASG_r10.getTimestamp(1); } catch (SQLException e) {} ASG_r10.close(); ASG_st10.close(); System.out.println(fechahora ); Statement ASG_st11 = ASGcondb.retCon().createStatement(); ResultSet ASG_r11 = ASG_st11.executeQuery("select dateadd(dd,0, datediff(dd,0, getdate() )) from prueba1 where campo1 = 3 "); try { ASG_r11.next(); fechahora = ASG_r11.getTimestamp(1); } catch (SQLException e) {} ASG_r11.close(); ASG_st11.close(); System.out.println(fechahora ); Statement ASG_st12 = ASGcondb.retCon().createStatement(); ResultSet ASG_r12 = ASG_st12.executeQuery("select count ( campo1 ) from prueba1 where campo4 > convert(datetime,'2007-10-22 00:00:00.0',121) "); try { ASG_r12.next(); cuatro = ASG_r12.getInt(1); } catch (SQLException e) {} ASG_r12.close(); ASG_st12.close(); System.out.println(cuatro );

Page 310: IfxToJava2

310 Statement ASG_st13 = ASGcondb.retCon().createStatement(); ResultSet ASG_r13 = ASG_st13.executeQuery("select count ( campo1 ) from prueba1 where convert(datetime,'2007-10-22 00:00:00.0',121) > campo4 "); try { ASG_r13.next(); cuatro = ASG_r13.getInt(1); } catch (SQLException e) {} ASG_r13.close(); ASG_st13.close(); System.out.println(cuatro ); } }

CÓDIGO OBJETO ORACLE import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class ctesfecha { static java.sql.Date fecha ; static java.sql.Timestamp fechahora ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; java.sql.Date dos ; java.sql.Timestamp tres ; int cuatro ; double cinco ; cuatro = 0; cinco = 0.0; uno = ""; dos = null; tres = null; ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("drop table prueba1 cascade constraints"); ASGcondb.activaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 integer , campo2 decimal(20,0) , campo3 date , campo4 timestamp ) "); dos = ASGfaux.cteIntToFechaJ(1) ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 1 , 1 , to_date(to_char(sysdate,'dd/mm/yyyy')) , sysdate ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 2 , 1 , {d '"+ dos +"'} , sysdate ) "); dos = ASGfaux.fecha( 39378 ) ; System.out.println(ASGfaux.formato_fecha(dos) ); cuatro = 39378 ; dos = ASGfaux.fecha( cuatro ) ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 3 , 40000 , {d '"+ dos +"'} , sysdate ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select to_date( to_date( (campo1 + 2415020 ),'J') ,'dd/mm/yyyy') from prueba1 where campo1 = 3 "); try { ASG_r1.next(); fecha = ASG_r1.getDate(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select to_date( to_date( (39379 + 2415020 ),'J') ,'dd/mm/yyyy') from prueba1 where campo1 = 3 "); try { ASG_r2.next(); fecha = ASG_r2.getDate(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select count ( campo1 ) from prueba1 where campo3 > to_date(39376 + 2415020 ,'J') "); try { ASG_r3.next(); cuatro = ASG_r3.getInt(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println(cuatro ); Statement ASG_st4 = ASGcondb.retCon().createStatement(); ResultSet ASG_r4 = ASG_st4.executeQuery("select count ( campo1 ) from prueba1 where 39376 > to_number(to_char(campo3 ,'J')) - 2415020 "); try { ASG_r4.next(); cuatro = ASG_r4.getInt(1); } catch (SQLException e) {} ASG_r4.close(); ASG_st4.close(); System.out.println(cuatro ); dos = ASGfaux.fecha("01/01/1900") ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 1 , 1 , to_date(to_char(sysdate,'dd/mm/yyyy')) , sysdate ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 2 , 1 , {d '"+ dos +"'} , sysdate ) "); dos = ASGfaux.fecha( ASGfaux.fecha("24/10/2007") ) ;

Page 311: IfxToJava2

311 System.out.println(ASGfaux.formato_fecha(dos) ); dos = ASGfaux.fecha("24/10/2007") ; dos = ASGfaux.fecha( dos ) ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 3 , 40000 , {d '"+ dos +"'} , sysdate ) "); Statement ASG_st5 = ASGcondb.retCon().createStatement(); ResultSet ASG_r5 = ASG_st5.executeQuery("select to_date( to_date( (campo1 + 2415020 ),'J') ,'dd/mm/yyyy') from prueba1 where campo1 = 3 "); try { ASG_r5.next(); fecha = ASG_r5.getDate(1); } catch (SQLException e) {} ASG_r5.close(); ASG_st5.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st6 = ASGcondb.retCon().createStatement(); ResultSet ASG_r6 = ASG_st6.executeQuery("select to_date( to_date('25/10/2007','dd/mm/yyyy') ,'dd/mm/yyyy') from prueba1 where campo1 = 3 "); try { ASG_r6.next(); fecha = ASG_r6.getDate(1); } catch (SQLException e) {} ASG_r6.close(); ASG_st6.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st7 = ASGcondb.retCon().createStatement(); ResultSet ASG_r7 = ASG_st7.executeQuery("select to_date( to_date(to_char(sysdate,'dd/mm/yyyy')) ,'dd/mm/yyyy') from prueba1 where campo1 = 3 "); try { ASG_r7.next(); fecha = ASG_r7.getDate(1); } catch (SQLException e) {} ASG_r7.close(); ASG_st7.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st8 = ASGcondb.retCon().createStatement(); ResultSet ASG_r8 = ASG_st8.executeQuery("select count ( campo1 ) from prueba1 where campo3 > to_date('22/10/2007','dd/mm/yyyy') "); try { ASG_r8.next(); cuatro = ASG_r8.getInt(1); } catch (SQLException e) {} ASG_r8.close(); ASG_st8.close(); System.out.println(cuatro ); Statement ASG_st9 = ASGcondb.retCon().createStatement(); ResultSet ASG_r9 = ASG_st9.executeQuery("select count ( campo1 ) from prueba1 where to_date('22/10/2007','dd/mm/yyyy') > campo3 "); try { ASG_r9.next(); cuatro = ASG_r9.getInt(1); } catch (SQLException e) {} ASG_r9.close(); ASG_st9.close(); System.out.println(cuatro ); tres = ASGfaux.fechahora("1900-01-01 00:00:00") ; System.out.println(tres ); ASGcondb.exeUpdate("insert into prueba1 values ( 1 , 1 , to_date(to_char(sysdate,'dd/mm/yyyy')) , sysdate ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 2 , 1 , to_date(to_char(sysdate,'dd/mm/yyyy')) , {ts '"+ tres +"'} ) "); tres = ASGfaux.fecha( ASGfaux.fechahora("2007-10-24 00:00:00") ) ; System.out.println(tres ); tres = ASGfaux.fechahora("2007-10-24 00:00:00") ; tres = ASGfaux.fecha( tres ) ; System.out.println(tres ); ASGcondb.exeUpdate("insert into prueba1 values ( 3 , 40000 , {d '"+ dos +"'} , {ts '"+ tres +"'} ) "); Statement ASG_st10 = ASGcondb.retCon().createStatement(); ResultSet ASG_r10 = ASG_st10.executeQuery("select to_date( campo3 ,'dd/mm/yyyy') from prueba1 where campo1 = 3 "); try { ASG_r10.next(); fechahora = ASG_r10.getTimestamp(1); } catch (SQLException e) {} ASG_r10.close(); ASG_st10.close(); System.out.println(fechahora ); Statement ASG_st11 = ASGcondb.retCon().createStatement(); ResultSet ASG_r11 = ASG_st11.executeQuery("select to_date(to_char( sysdate ,'dd/mm/yyyy')) from prueba1 where campo1 = 3 "); try { ASG_r11.next(); fechahora = ASG_r11.getTimestamp(1); } catch (SQLException e) {} ASG_r11.close(); ASG_st11.close(); System.out.println(fechahora ); Statement ASG_st12 = ASGcondb.retCon().createStatement(); ResultSet ASG_r12 = ASG_st12.executeQuery("select count ( campo1 ) from prueba1 where campo4 > timestamp '2007-10-22 00:00:00.0' "); try { ASG_r12.next(); cuatro = ASG_r12.getInt(1); } catch (SQLException e) {}

Page 312: IfxToJava2

312 ASG_r12.close(); ASG_st12.close(); System.out.println(cuatro ); Statement ASG_st13 = ASGcondb.retCon().createStatement(); ResultSet ASG_r13 = ASG_st13.executeQuery("select count ( campo1 ) from prueba1 where timestamp '2007-10-22 00:00:00.0' > campo4 "); try { ASG_r13.next(); cuatro = ASG_r13.getInt(1); } catch (SQLException e) {} ASG_r13.close(); ASG_st13.close(); System.out.println(cuatro ); } }

CÓDIGO OBJETO DB2 import java.sql.*; import ASGdb.*; import ASGdbutil.*; import ASGutil.*; public class ctesfecha { static java.sql.Date fecha ; static java.sql.Timestamp fechahora ; private static AccesDB ASGcondb = null; public static void main(String argv[]) throws Exception { ASGcon.cargaparamcon(); ASGcondb = new AccesDB("datos"); ASGcondb.HayTransac(); String uno ; java.sql.Date dos ; java.sql.Timestamp tres ; int cuatro ; double cinco ; cuatro = 0; cinco = 0.0; uno = ""; dos = null; tres = null; ASGcondb.desactivaControlError(); ASGcondb.exeUpdate("drop table prueba1 "); ASGcondb.activaControlError(); ASGcondb.exeUpdate("create table prueba1 ( campo1 integer , campo2 decimal(20,0) , campo3 date , campo4 timestamp ) "); dos = ASGfaux.cteIntToFechaJ(1) ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 1 , 1 , current date , current timestamp ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 2 , 1 , {d '"+ dos +"'} , current timestamp ) "); dos = ASGfaux.fecha( 39378 ) ; System.out.println(ASGfaux.formato_fecha(dos) ); cuatro = 39378 ; dos = ASGfaux.fecha( cuatro ) ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 3 , 40000 , {d '"+ dos +"'} , current timestamp ) "); Statement ASG_st1 = ASGcondb.retCon().createStatement(); ResultSet ASG_r1 = ASG_st1.executeQuery("select date( date( (campo1 + 693595) ) ) from prueba1 where campo1 = 3 "); try { ASG_r1.next(); fecha = ASG_r1.getDate(1); } catch (SQLException e) {} ASG_r1.close(); ASG_st1.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st2 = ASGcondb.retCon().createStatement(); ResultSet ASG_r2 = ASG_st2.executeQuery("select date( date( (39379 + 693595) ) ) from prueba1 where campo1 = 3 "); try { ASG_r2.next(); fecha = ASG_r2.getDate(1); } catch (SQLException e) {} ASG_r2.close(); ASG_st2.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st3 = ASGcondb.retCon().createStatement(); ResultSet ASG_r3 = ASG_st3.executeQuery("select count ( campo1 ) from prueba1 where campo3 > date(39376 + 693595) "); try { ASG_r3.next(); cuatro = ASG_r3.getInt(1); } catch (SQLException e) {} ASG_r3.close(); ASG_st3.close(); System.out.println(cuatro ); Statement ASG_st4 = ASGcondb.retCon().createStatement(); ResultSet ASG_r4 = ASG_st4.executeQuery("select count ( campo1 ) from prueba1 where 39376 > days(campo3 ) - 693595 "); try { ASG_r4.next(); cuatro = ASG_r4.getInt(1); } catch (SQLException e) {} ASG_r4.close(); ASG_st4.close(); System.out.println(cuatro ); dos = ASGfaux.fecha("01/01/1900") ; System.out.println(ASGfaux.formato_fecha(dos) );

Page 313: IfxToJava2

313 ASGcondb.exeUpdate("insert into prueba1 values ( 1 , 1 , current date , current timestamp ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 2 , 1 , {d '"+ dos +"'} , current timestamp ) "); dos = ASGfaux.fecha( ASGfaux.fecha("24/10/2007") ) ; System.out.println(ASGfaux.formato_fecha(dos) ); dos = ASGfaux.fecha("24/10/2007") ; dos = ASGfaux.fecha( dos ) ; System.out.println(ASGfaux.formato_fecha(dos) ); ASGcondb.exeUpdate("insert into prueba1 values ( 3 , 40000 , {d '"+ dos +"'} , current timestamp ) "); Statement ASG_st5 = ASGcondb.retCon().createStatement(); ResultSet ASG_r5 = ASG_st5.executeQuery("select date( date( (campo1 + 693595) ) ) from prueba1 where campo1 = 3 "); try { ASG_r5.next(); fecha = ASG_r5.getDate(1); } catch (SQLException e) {} ASG_r5.close(); ASG_st5.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st6 = ASGcondb.retCon().createStatement(); ResultSet ASG_r6 = ASG_st6.executeQuery("select date( date('25/10/2007') ) from prueba1 where campo1 = 3 "); try { ASG_r6.next(); fecha = ASG_r6.getDate(1); } catch (SQLException e) {} ASG_r6.close(); ASG_st6.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st7 = ASGcondb.retCon().createStatement(); ResultSet ASG_r7 = ASG_st7.executeQuery("select date( current date ) from prueba1 where campo1 = 3 "); try { ASG_r7.next(); fecha = ASG_r7.getDate(1); } catch (SQLException e) {} ASG_r7.close(); ASG_st7.close(); System.out.println(ASGfaux.formato_fecha(fecha) ); Statement ASG_st8 = ASGcondb.retCon().createStatement(); ResultSet ASG_r8 = ASG_st8.executeQuery("select count ( campo1 ) from prueba1 where campo3 > date('22/10/2007') "); try { ASG_r8.next(); cuatro = ASG_r8.getInt(1); } catch (SQLException e) {} ASG_r8.close(); ASG_st8.close(); System.out.println(cuatro ); Statement ASG_st9 = ASGcondb.retCon().createStatement(); ResultSet ASG_r9 = ASG_st9.executeQuery("select count ( campo1 ) from prueba1 where date('22/10/2007') > campo3 "); try { ASG_r9.next(); cuatro = ASG_r9.getInt(1); } catch (SQLException e) {} ASG_r9.close(); ASG_st9.close(); System.out.println(cuatro ); tres = ASGfaux.fechahora("1900-01-01 00:00:00") ; System.out.println(tres ); ASGcondb.exeUpdate("insert into prueba1 values ( 1 , 1 , current date , current timestamp ) "); ASGcondb.exeUpdate("insert into prueba1 values ( 2 , 1 , current date , {ts '"+ tres +"'} ) "); tres = ASGfaux.fecha( ASGfaux.fechahora("2007-10-24 00:00:00") ) ; System.out.println(tres ); tres = ASGfaux.fechahora("2007-10-24 00:00:00") ; tres = ASGfaux.fecha( tres ) ; System.out.println(tres ); ASGcondb.exeUpdate("insert into prueba1 values ( 3 , 40000 , {d '"+ dos +"'} , {ts '"+ tres +"'} ) "); Statement ASG_st10 = ASGcondb.retCon().createStatement(); ResultSet ASG_r10 = ASG_st10.executeQuery("select date( campo3 ) from prueba1 where campo1 = 3 "); try { ASG_r10.next(); fechahora = ASG_r10.getTimestamp(1); } catch (SQLException e) {} ASG_r10.close(); ASG_st10.close(); System.out.println(fechahora ); Statement ASG_st11 = ASGcondb.retCon().createStatement(); ResultSet ASG_r11 = ASG_st11.executeQuery("select date( current timestamp ) from prueba1 where campo1 = 3 "); try { ASG_r11.next(); fechahora = ASG_r11.getTimestamp(1); } catch (SQLException e) {} ASG_r11.close(); ASG_st11.close(); System.out.println(fechahora ); Statement ASG_st12 = ASGcondb.retCon().createStatement(); ResultSet ASG_r12 = ASG_st12.executeQuery("select count ( campo1 ) from prueba1 where campo4 > '2007-10-22 00:00:00.0' "); try { ASG_r12.next(); cuatro = ASG_r12.getInt(1); } catch (SQLException e) {}

Page 314: IfxToJava2

314 ASG_r12.close(); ASG_st12.close(); System.out.println(cuatro ); Statement ASG_st13 = ASGcondb.retCon().createStatement(); ResultSet ASG_r13 = ASG_st13.executeQuery("select count ( campo1 ) from prueba1 where '2007-10-22 00:00:00.0' > campo4 "); try { ASG_r13.next(); cuatro = ASG_r13.getInt(1); } catch (SQLException e) {} ASG_r13.close(); ASG_st13.close(); System.out.println(cuatro ); } }

Page 315: IfxToJava2

ÍNDICE DE FIGURAS Figura 1: Interfaces proporcionados por Informix-4GL .......................................................... 9 Figura 2: Ficheros de los que consta una aplicación en Informix .............................................11 Figura 3: Tipos de bloques en un programa.........................................................................14 Figura 4: Componentes del traductor .................................................................................25 Figura 5: Palabras reservadas de Informix ..........................................................................26 Figura 6: Estructura básica de un módulo de programa........................................................58 Figura 7: Ejecución de la aplicación �hola.4gl� sobre Informix .................................................61 Figura 8: Resultado de la ejecución del programa �hola.java� como aplicación modo texto ...........61 Figura 9: Ejecución del programa �hola.java� como aplicación gráfica .......................................62 Figura 10: Ejecución del programa �hola.java� como aplicación Web ........................................62 Figura 11: Resultado de ejecución de un programa con menú en Informix................................83 Figura 12: Resultado de ejecución de un programa con menú en Java .....................................83 Figura 13: Propiedades de la base de datos SQL Server ......................................................202 Figura 14: Lista te tareas del proyecto .............................................................................227 Figura 15: Diagrama Gantt de tareas del proyecto .............................................................227

Page 316: IfxToJava2

316

ÍNDICE DE TABLAS Tabla 1: Sentencias compuestas de Informix-4GL ................................................................14 Tabla 2. Ámbito de referencia de los identificadores 4GL .......................................................16 Tabla 3: Tipos de datos 4GL .............................................................................................18 Tabla 4: Operadores de las expresiones 4GL .......................................................................21 Tabla 5. Operadores sobre expresiones enteras ...................................................................22 Tabla 6: Operadores reconocidos por el analizador léxico ......................................................27 Tabla 7: Constantes reconocidas por el analizador léxico .......................................................27 Tabla 9: Mapeo entre tipos de datos Informix-4GL y JAVA .....................................................84 Tabla 10: Valor de inicialización de variables .......................................................................85 Tabla 11: Asigación de expresiones tipo fecha .....................................................................85 Tabla 12: Asignación de expresiones tipo fecha/hora ............................................................86 Tabla 13: Asignación de expresiones tipo fecha a entero .......................................................86 Tabla 14: Estándar SQL...................................................................................................92 Tabla 15: Sentencias de definición de datos ........................................................................93 Tabla 16: Sentencias de manipulación de datos ...................................................................93 Tabla 17: Sentencias de manipulación de cursores ...............................................................93 Tabla 18: Sentencias de optimización-Información ...............................................................93 Tabla 19: Sentencias de control de acceso a los datos ..........................................................94 Tabla 20: Sentencias de integridad de los datos...................................................................94 Tabla 21: Sentencias de manipulación dinámica de datos ......................................................94 Tabla 22: Tipos de datos primarios ..................................................................................155 Tabla 23: Sinónimos de tipos de datos primarios................................................................156 Tabla 24: Tipos de datos JDBC........................................................................................157 Tabla 25: Mapeos de datos Informix-SQL a SQL JDBC.........................................................160 Tabla 26: Mapeo de tipos de datos SqlServer a SQL JDBC ...................................................164 Tabla 27: Tipos de datos numéricos de Oracle ...................................................................165 Tabla 28: Mapeo de tipos de datos Oracle a SQL JDBC........................................................167 Tabla 29: Mapeo de tipos de datos DB2 a SQL JDBC...........................................................169 Tabla 30: Mapeo entre tipos de datos Informix-SQL y el resto de gestores .............................170 Tabla 31: Mapeos de datos Informix-SQL a implementaciones JDBC de los gestores ................171 Tabla 32: Mapeo entre tipos de datos SQL JDBC y Java.......................................................173 Tabla 33: Mapeo entre tipos de datos Java y SQL JDBC.......................................................174 Tabla 34: Funciones para recuperación de datos del gestor de bases de datos ........................175 Tabla 35: Conversiones implícitas soportadas por Informix ..................................................176 Tabla 36: Conversiones soportadas por SqlServer ..............................................................177 Tabla 37: Conversiones implícitas soportadas por Oracle .....................................................178 Tabla 38: Conversiones implícitas soportadas por DB2........................................................178 Tabla 39: Conversiones implícitas necesarias para SqlServer................................................179 Tabla 40: Conversiones implícitas necesarias para Oracle ....................................................180 Tabla 41: Conversiones implícitas necesarias para DB2 .......................................................182 Tabla 42: Precedencia de operadores en Informix-SQL........................................................199 Tabla 43: Precedencia de operadores en SqlServer.............................................................203 Tabla 44: Precedencia de operadores Oracle .....................................................................206 Tabla 45: Precedencia de operadores Db2.........................................................................208 Tabla 46: Formatos por defecto de Informix-SQL ...............................................................210 Tabla 47: Formatos por defecto de SqlServer ....................................................................211 Tabla 48: Formatos por defecto de Oracle.........................................................................212

Page 317: IfxToJava2

317

Tabla 49: Formatos por defecto de Db2............................................................................213 Tabla 50: Formatos del lenguaje de programación Java.......................................................214 Tabla 51: Ejemplo de configuración de entornos ................................................................215 Tabla 52: Uso de constantes tipo fecha en sentencias SQL...................................................220 Tabla 53: Valores numéricos asociados a una fecha en cada gestor.......................................220 Tabla 54: Coste del proyecto ..........................................................................................228 Tabla 55: Formato de fecha en función del idioma establecido..............................................232

Page 318: IfxToJava2

318

INDICE DE CUADROS Cuadro 1: Código fuente mínimo de un programa Informix-4GL .............................................59 Cuadro 2: Relación entre código objeto modo texto y modo gráfico.........................................60 Cuadro 3: Makefile y ASGmakefile.....................................................................................63 Cuadro 4: Ejemplo módulo principal de programa multimódulo...............................................65 Cuadro 5: Ejemplo de módulo de programa multimódulo......................................................65 Cuadro 6: Ejemplo de módulo de programa multimódulo......................................................66 Cuadro 7: Ejemplo de bloque de programa globals ..............................................................67 Cuadro 8: Ejemplo módulo de programa globals ..................................................................68 Cuadro 9: Programa multimódulo completo con sección globals.............................................70 Cuadro 10: Ejemplo de definición de funciones ....................................................................72 Cuadro 11: Ejemplo de función con valores de retorno..........................................................73 Cuadro 12: Sentencias de control de flujo...........................................................................79 Cuadro 13: Ejemplo sentencias menú ................................................................................82

Page 319: IfxToJava2

319

REFERENCIAS BIBLIOGRAFICAS [INFOR89] Informix 4GL: User Guide (Informix-4GL V4.0), Informix Software Inc., Informix Press, 1989.

[INFOR91] Informix Guide to SQL: Tutorial (Informix-SQL V4.1), Informix Software Inc., Informix Press, 1991.

[INFOR91] Informix Guide to SQL: Reference (Informix-SQL V4.1), Informix Software Inc., Informix Press, 1991.

[INFOR91] SQL Quick Syntax Guide (Informix-SQL V4.1), Informix Software Inc., Informix Press, 1991.

[INFOR94] Informix 4GL: Quick Syntax (Version 6.0), Informix Software Inc., Informix Press, 1994.

[INFOR94] Informix SQL: User Guide (Version 6.0), Informix Software Inc., Informix Press, 1994.

[INFOR94] Informix SQL: Reference (Version 6.0), Informix Software Inc., Informix Press, 1994.

[INFOR97] Informix Guide to SQL: Syntax (Version 9.1), Informix Software Inc., Informix Press, 1997.

[INFOR98] Informix Guide to SQL: Reference (Version 7.3), Informix Software Inc., Informix Press, 1998.

[INFOR99] Informix 4GL: Referencia Manual (Version 7.3), Informix Software Inc., Informix Press, 1999.

[INFOR00] Informix JDBC Drive: Programmer�s Guide, Informix Software Inc., Informix Press, 2000.

[INTER03] IBM Informix Guide to SQL: Reference (Version 9.4), International Business Machines Corporation, International Business Machines Corporation, 2003.

[INTER04] IBM Informix JDBC Driver Programmer�s Guide, International Business Machines Corporation, International Business Machines Corporation, 2004.

[INTER04] IBM Informix JDBC Driver Programmer�s Guide, International Business Machines Corporation, International Business Machines Corporation, 2004.

[ADVA98] La Biblia de Oracle8, Advanced Informatcion Systems Inc., Ediciones Anaya Multimedia S.A., 1998.

[DIAN01] Oracle 9i: SQL Reference (Release 9.0.1), Diana Lorentz, Oracle Corporation, 2001.

[DIAN02] Oracle 9i: SQL Reference (Release 9.2), Diana Lorentz, Oracle Corporation, 2002.

[KEVI03] Oracle 9i: Manual del administrador, Kevin Loney, Marlene Theriault, McGraw-Hill/Osborne, 2003.

[DIAN06] Oracle Database SQL Reference 10g (Release 10.2), Diana Lorentz, Oracle Corporation, 2006.

[KEVI01] Oracle Database 10g: Complete Reference, Kevin Loney, McGraw-Hill/Osborne, 2004.

[MICR02] SQL Server 2000 Driver for JDBC User�s Guide and Reference, Microsoft, Microsoft, 2002.

[MICR02] Libros de pantalla SQL Server 2000, Microsoft, Microsoft, 2002.

[MICR07] Libros de pantalla SQL Server 2005, Microsoft, Microsoft, 2007.

Page 320: IfxToJava2

320

[INTE03] SQL Reference for Cross-Platform Development, International Business Machines Corporation, International Business Machines Corporation, 2003.

[INTE02] SQL Reference Volume 1 (Version 8), International Business Machines Corporation, International Business Machines Corporation, 2002.

[INTE02] SQL Reference Volume 2 (Version 8), International Business Machines Corporation, International Business Machines Corporation, 2002.

[INTE04] SQL Reference Volume 1 (Version 8.2), International Business Machines Corporation, International Business Machines Corporation, 2004.

[INTE04] SQL Reference Volume 2 (Version 8.2), International Business Machines Corporation, International Business Machines Corporation, 2004.

[WHEI05] Microsoft SQL Server to IBM DB2 UDB Conversion Guide, Whei-Jen Chen, Alain Fisher, Stefan Hummel, Shailendra Kishore, Bin TeahTed Wasserman, International Business Machines Corporation, 2005.

[MICR02] Migrating Informix Databases to Microsoft SQL Server 2000, Microsoft Corporation, Microsoft TechNet, 2002.

[MICR99] Migrar bases de datos de Oracle a MS SQL Server 7.0, Microsoft Corporation, Microsoft TechNet, 1999.

[EXAL03] Migrating Informix 4GL Applications to J2EE�1.3 with the b+ J2EE� Application Generator, Exaltec Software, Exaltec Software Limited, 2003.

[SANJ95] INFORMIX 6.X to Oracle7: Comparison of Tables and Features, Sanjoy Mondal, Dan Mohler, Oracle Corporation, 1995.

[SANJ94] Migrating from INFORMIX 5.X to Oracle7: Design Considerations, Sanjoy Mondal, Dan Mohler, Oracle Corporation, 1994.

[DONA96] Converting Applications: INFORMIX 4GL to Oracle7, Donal Daly, Geeta Deodhar, Lakshmana Pillai, Lynne Chaddon, Nik Pollak, Robert Froeber, Sanjoy Mondal, Subhash Jawahrani, Breda McColgan, Oracle Corporation, 1996.

[ORAC96] Database Conversion Guide: DB2/MVS to Oracle7, Oracle Corporation, Oracle Corporation, 1996.

[ORAC03] Migrating Applications from Microsoft SQL Server to Oracle9i Database, Oracle Corporation, Oracle Corporation, 2003.

[BRUE00] Thinking in Java 2ª Ed., Bruce Eckel, Prentice Hall, 2000.

[BRUE03] Thinking in Java 3ª Ed., Bruce Eckel, Prentice Hall, 2003.

[JOSE07] Dominie JavaScript, José López Quijano, Ra-Ma Editorial, 2007.