Etiqueta

03 enero 2011

Consultas (SQL) dinámicas y sencillas

La capacidad que Omnis Studio nos proporciona para trabajar con objetos, será usada en este práctico ejemplo, para que el programador pueda construir nuevas consultas (query’s) sobre la base de datos, sin que sea necesario alterar el código de la aplicación, al añadir o modificar una consulta.

Puede descargar la librería Ejemplo.lib en este link.

Para nuestro ejemplo partimos de una tabla o esquema ALUMNOS, para el cual creamos un objeto de tipo “Query”, este será la base que usará la aplicación para construir la “interface” de búsqueda al usuario.

Posteriormente el programador se limitará a crear y/o modificar nuevos objetos “Query”, pero no necesitará escribir nuevo código.

En nuestro ejemplo crearemos la “Query” “Bus_Alumno” como sigue:

Detalle de la consulta: Bus_Alumno

Esquema Columna....Alias
ALUMNOS NUMEXPALU..Expediente
ALUMNOS APEL1......Primer apellido
ALUMNOS APEL2......Segundo apellido
ALUMNOS NOMBRE.....Nombre
ALUMNOS DNI........DNI
ALUMNOS FALTAN.....Faltan
ALUMNOS AVISO......Aviso
ALUMNOS ROWID......Puntero

Extensión: (Almacena la última consulta efectuada por el usuario)

La columna “Alias” contendrá la denominación que será usada para construir el “pop-menú” desde donde el usuario seleccionará el campo de comparación.

Además de las columnas o datos seleccionados del esquema “ALUMNOS”, se incluye la columna “ROWID”, para permitir la selección de una fila única por parte del usuario (Véase ventana de “Resultados”)

La ventana de búsqueda es auto-ampliable, permitiendo la inclusión de hasta 10 valores de comparación, su aspecto totalmente desplegada sería el que se muestra más bajo. Cabe destacar que el objeto “Bus_Alumno” guardará siempre la última consulta realizada por el usuario, incluso aunque abandone la aplicación.


A continuación mostramos las variables asociadas a la clase (Ventana “Buscar”) y los métodos asociados:
Variables, tipo y uso
bCampos1…bCampos10, tipo: Lista, Uso: Lista de los datos objeto de comparación (Nombres alias)
bCompara1…bCompara10, tipo: Lista, Uso: Lista de opciones de comparación
Valor1…Valor10, tipo: Carácter, Uso: Guarda el primer posible valor de comparación establecido

pQuery, tipo: Carácter Contiene una copia de las condiciones de búsqueda establecidas
Método: $construct
Variables locales
CuentaClon, tipo: Entero, Uso: Usado para crear el duplicado de las listas "bCampos" y "bCompara"
Item, tipo: Referencia, Uso: Referencia al primer dibujo a fijar en el fondo de la ventana
Ref_Col, tipo: Referencia, Uso: Referencia a cada columna en la "query" de búsqueda para la vista en selección
Variables parámetros
Busqueda, tipo: Carácter, Uso: Contiene el nombre de la "query" de búsqueda para la vista en selección
; Crea desplegables para los campos de búsqueda
Do bCampos1.$define(#S1,#S2)
Do bCampos1.$clear()
Do bCampos1.$add($clib.$queries.[Busqueda].$objs.$first().$alias,$clib.
$queries.[Busqueda].$objs.$first().$colname)
Set reference Ref_Col to $clib.$queries.[Busqueda].$objs.$first()
While Ref_Col
Set reference Ref_Col to $clib.$queries.[Busqueda].$objs.$next(Ref_Col)
If Ref_Col.$alias<>''&Ref_Col.$alias<>'Puntero'
Do bCampos1.$add(Ref_Col.$alias,Ref_Col.$colname)

End If
End While
Do bCampos1.$line.$assign(1)
For CuentaClon from 2 to 10 step 1
Do bCampos[CuentaClon].$copydefinition(bCampos1)
Do bCampos[CuentaClon].$merge(bCampos1,,,kTrue)
Do bCampos[CuentaClon].$line.$assign(1)
End For
; Crea desplegables para las comparaciones de búsqueda
Do bCompara1.$define(#S1)
Do bCompara1.$clear()
Do bCompara1.$add('contiene')
Do bCompara1.$add('empieza por')
Do bCompara1.$add('es')
Do bCompara1.$add('no es')
Do bCompara1.$add('mayor o igual a')
Do bCompara1.$add('menor o igual a')
Do bCompara1.$line.$assign(1)
For CuentaClon from 2 to 10 step 1
Do bCompara[CuentaClon].$copydefinition(bCompara1)
Do bCompara[CuentaClon].$merge(bCompara1,,,kTrue)
Do bCompara[CuentaClon].$line.$assign(1)
End For
Clear range of fields Valor1 to Valor10
Do $cwind.$objs.Opciones.$objs.Valor1.$enabled.$assign(kTrue)
; Pasa el parámetro de búsqueda a la variable global "pQuery" para no perderlo
Calculate pQuery as Busqueda
Método: PasaValor
Variables parámetros
Valor, tipo: Carácter, Uso: Contiene el valor a comparar
; Pasa el símbolo de consulta
Switch lst(#S1)
Case 'contiene'
Calculate bCondicion as con(bCondicion," LIKE '%",Valor,"%' ")
Case 'empieza por'
Calculate bCondicion as con(bCondicion," LIKE '",Valor,"%' ")
Case 'es'
Calculate bCondicion as con(bCondicion," = '",Valor,"' ")
Case 'no es'
Calculate bCondicion as con(bCondicion," <> '",Valor,"' ")
Case 'mayor o igual a'
Calculate bCondicion as con(bCondicion," >= '",Valor,"' ")
Case 'menor o igual a'
Calculate bCondicion as con(bCondicion," <= '",Valor,"' ")
End Switch
Botón “Más opciones”: $event
On evClick ;; Amplia el número de opciones en la ventana
If $cwind.$objs.Opciones.$height<>345
Do $cwind.$objs.Opciones.$height.$assign($cwind.$objs.Opciones.$height+33)
Do $cwind.$height.$assign($cwind.$height+33)
Switch $cwind.$objs.Opciones.$height
Case 81
Do $cwind.$objs.Opciones.$objs.Valor2.$enabled.$assign(kTrue)
Case 114
Do $cwind.$objs.Opciones.$objs.Valor3.$enabled.$assign(kTrue)
Case 147
Do $cwind.$objs.Opciones.$objs.Valor4.$enabled.$assign(kTrue)
Case 180
Do $cwind.$objs.Opciones.$objs.Valor5.$enabled.$assign(kTrue)
Case 213
Do $cwind.$objs.Opciones.$objs.Valor6.$enabled.$assign(kTrue)
Case 246
Do $cwind.$objs.Opciones.$objs.Valor7.$enabled.$assign(kTrue)
Case 279
Do $cwind.$objs.Opciones.$objs.Valor8.$enabled.$assign(kTrue)
Case 312
Do $cwind.$objs.Opciones.$objs.Valor9.$enabled.$assign(kTrue)
Case 345
Do $cwind.$objs.Opciones.$objs.Valor10.$enabled.$assign(kTrue)
End Switch
End If
Botón “Menos opciones”: $event
On evClick ;; Reduce el número de opciones en ventana
If $cwind.$objs.Opciones.$height<>48
Do $cwind.$objs.Opciones.$height.$assign($cwind.$objs.Opciones.$height-33)
Do $cwind.$height.$assign($cwind.$height-33)
Switch $cwind.$objs.Opciones.$height
Case 48
Do $cwind.$objs.Opciones.$objs.Valor2.$enabled.$assign(kFalse)
Calculate Valor2 as ''
Case 81
Do $cwind.$objs.Opciones.$objs.Valor3.$enabled.$assign(kFalse)
Calculate Valor3 as ''
Case 114
Do $cwind.$objs.Opciones.$objs.Valor4.$enabled.$assign(kFalse)
Calculate Valor4 as ''
Case 147
Do $cwind.$objs.Opciones.$objs.Valor5.$enabled.$assign(kFalse)
Calculate Valor5 as ''
Case 180
Do $cwind.$objs.Opciones.$objs.Valor6.$enabled.$assign(kFalse)
Calculate Valor6 as ''
Case 213
Do $cwind.$objs.Opciones.$objs.Valor7.$enabled.$assign(kFalse)
Calculate Valor7 as ''
Case 246
Do $cwind.$objs.Opciones.$objs.Valor8.$enabled.$assign(kFalse)
Calculate Valor8 as ''
Case 279
Do $cwind.$objs.Opciones.$objs.Valor9.$enabled.$assign(kFalse)
Calculate Valor9 as ''
Case 312
Do $cwind.$objs.Opciones.$objs.Valor10.$enabled.$assign(kFalse)
Calculate Valor10 as ''
End Switch
Do $redraw()
End If
Botón “Buscar”: $event
Variables locales
ItemAnterior, tipo: Entero, Uso: Contiene el nombre del campo a comparar, seleccionado en la línea anterior
Replica, tipo: Entero, Uso: Usado para recorrer cada una de las 10 líneas posibles de comparación
On evClick ;; Compone la consulta sobre la variable "bCondicion"
Calculate bCondicion as ''
If Valor1<>''
Calculate bCondicion as 'where '
Set current list bCampos1
Calculate ItemAnterior as bCampos1.$line
Calculate bCondicion as con(bCondicion,bCampos1.#S2)
Set current list bCompara1
Do method PasaValor (Valor1)
End If
For Replica from 2 to 10 step 1
If Valor[Replica]<>''
Set current list bCampos[Replica]
If bCampos[Replica].$line=ItemAnterior
Calculate bCondicion as con(bCondicion,' OR ')
Else
Calculate bCondicion as con(bCondicion,' AND ')
End If
Calculate ItemAnterior as bCampos[Replica].$line
Calculate bCondicion as con(bCondicion,bCampos[Replica].#S2)
Set current list bCompara[Replica]
Do method PasaValor (Valor[Replica])
End If
End For
; Pasa la misma consulta a la ventana de vista
Calculate $clib.$queries.[pQuery].$extraquerytext as bCondicion
Do $topwind.$close()
Esto será todo lo necesario para que el usuario construya una búsqueda, el resultado será una consulta SQL, preparada para ser lanzada a la base de datos.
Ahora nos centraremos en como presentar el resultado de la petición al usuario, para esto usaremos la clase ventana “Resultados”, a continuación mostramos el aspecto de esta ventana, así como sus variables y procedimientos.



Esta ventana tiene como finalidad mostrar los resultados de la última búsqueda realizada por el usuario. En la parte superior se recuerda la consulta realizada.
Variables asociadas a esta clase
iBusqueda, tipo: Carácter, Uso: Contiene una copia del nombre de la "query" en selección
Método: $construct
Variables locales
Item, tipo: Referencia, Uso: Referencia al primer dibujo a fijar en el fondo de la ventana
lStatus, tipo: Entero, Uso: Recoge el resultado de la sentencia "fetch"
Nom_Col, tipo: Carácter, Uso: Contiene los nombres alias de las columnas en la "query" de búsqueda en selección
Ref_Col, tipo: Referencia, Uso: Referencia a cada columna en la "query" de búsqueda para la vista en selección
Variables parámetros
Busqueda, tipo: Carácter, Uso: Contiene una el nombre de la "query" en selección
Calculate Nom_Col as $clib.$queries.[Busqueda].$objs.$first().$alias
Set reference Ref_Col to $clib.$queries.[Busqueda].$objs.$first()

For #1 from 2 to $clib.$queries.[Busqueda].$objs.$count()-1 step 1

Set reference Ref_Col to $clib.$queries.[Busqueda].$objs.$next(Ref_Col)

Calculate Nom_Col as con(Nom_Col,",",Ref_Col.$alias)

End For

Calculate $cwind.$objs.Resultados_headedlistbox_1023.$columnnames as Nom_Col

Calculate $cwind.$objs.Resultados_headedlistbox_1023.$colcount as
$clib.$queries.[Busqueda].$objs.$count()-1
Do iVerList.$definefromsqlclass(Busqueda)

Do iVerList.$sessionobject.$assign(iSessionObj) Returns #F

Do iVerList.$select() Returns lStatus

Do iVerList.$fetch(kFetchAll) Returns lStatus

Do iVerList.$line.$assign(1)
; Pasa el parámetro de busqueda a la variable de clase "iBusqueda" para no perderlo
Calculate iBusqueda as Busqueda
Do $root.$redraw()
Acciones sobre la lista: $event
Variables locales
Nom_Col, tipo: Carácter, Uso: Contiene el nombre de la columna seleccionada
Ref_Col, tipo: Referencia, Uso: Referencia a cada columna de la "query" en selección
On evDoubleClick
Do $topwind.$close()
On evHeaderClick ;; Clasifica los elementos según la columna seleccionada
Switch pColumnNumber
Case 1
Calculate Nom_Col as con("iVerList.",$clib.$queries.[iBusqueda].$objs.$first().$alias)
Do iVerList.$sort([Nom_Col])
Default
Set reference Ref_Col to $clib.$queries.[iBusqueda].$objs.$first()
For #1 from 2 to pColumnNumber step 1
Set reference Ref_Col to $clib.$queries.[iBusqueda].$objs.$next(Ref_Col)
Calculate Nom_Col as con("iVerList.",Ref_Col.$alias)
Do iVerList.$sort([Nom_Col])
End For
End Switch
Do $cwind.$redraw()
Sigo animando a todos los lectores de este blog a que dejéis vuestros animadores comentarios, eso permitirá que continúe añadiendo mis experiencias al mismo.

Ya sabéis que también podéis contactar conmigo a través de Skipe e incluso (si así lo deseáis) podríais colaborar con la publicación de vuestras propias experiencias, sería estupendo que este blog se convirtiera en un punto de encuentro para todos los que “nos pegamos” con el desarrollo de aplicaciones en Omnis Studio.

No hay comentarios: