Sentencias Generadas.
Las sentencias generadas para los filtros condicionales son similares a las generadas en el caso de filtros estándar (sin la clásula WHEN). La diferencia principal es que se tienen todos los strings posibles y de acuerdo a las condiciones se concatenan los que correspondan. Además, los valores de las variables van instanciados.
Ejemplo
- El filtro CliDir >= &CliDir or null(&CliDir) genera la sentencia:
SELECT [CliDir], [CliNom], [CliId] FROM [CLIENTES] (NOLOCK) WHERE [CliDir] = ? or (?=' ') ORDER BY [CliId]
- Si ese filtro se hace condicional: CliDir >= &CliDir WHEN not null(&cliDir) la sentencia generada será:
1. Cuando la variable &CliDir sea nula:
SELECT [CliNom], [CliId] FROM [CLIENTES] (NOLOCK) ORDER BY [CliId]
2. Cuando la variable &CliDir tenga valor:
SELECT [CliDir], [CliNom], [CliId] FROM [CLIENTES] (NOLOCK) WHERE [CliDir] = 'Miguelete 1234' ORDER BY [CliId]'
Órdenes condicionales
Es posible especificar órdenes de navegación alternativas dependiendo de las necesidades de la aplicación. La sintaxis correspondiente es:
[ORDER] <OrderAttList> [WHEN <Constraint1>]
[ORDER <OrderAttList1> [WHEN <Constraint2>]
...
<OrderAttListX> es una lista de atributos separados por espacios o comas que indican el orden de navegación. Si se desea un orden descendente por alguno de los atributos se lo encierra entre paréntesis curvos.
<ConstraintX> es la condición que habilita el <OrderAttList> correspondiente.
Si ninguna de las Constraints es verdadera y no existe un Order incondicional (sin la cláusula WHEN) el orden de navegación es indefinido. Indefinido, en este caso, significa que puede variar de DBMS en DBMS e, inclusive, en ejecuciones sucesivas.
Si mas de una de las Constraints es verdadera, se toma el orden de la primer cláusula ORDER definida, por este motivo, deberia ser el orden preferido para las consultas.
Si se especifican ordenes condicionales pero el generador no lo soporta, el órden de navegación será el especificado como orden incondicional o, si no lo hubiera, la llave primaria de la tabla base del grupo. Además, se generará el mensaje de código spc0054 -' Unsupported conditional order %2. Using default order in %1.'- en el diagrama de navegación. (La especificación en Diseño asume una generación SQL en un DBMS no determinado)
No se soportan órdenes condicionales cuando se realizan Breaks. Se generará el mensaje de código spc0055 -' Conditional order in group starting at line %1 not allowed (Break group).'- en el diagrama de navegación.
Consideraciones generales
- Sólo aplican a generadores que utilizan SQL como método de acceso a la base de datos
- Si el Constraint contiene atributos, estos son considerados como instanciados. En otras palabras, el Constraint se evalúa antes de iniciar la navegación y no cambia durante ésta.
- Performance
Por la forma de implementación, se espera que los grupos con orden o filtros condicionales no sean utilizados dentro de loops de alto nivel de ocurrencias. Podrían provocar problemas de performance ya que las sentencias SQL se arman dinámicamente y el tiempo de "analisis" que, en cada ejecución, debe hacer el DBMS puede ser bastante alto para estas situaciones.
Fuera de lo mencionado antes, se esperan mejoras sensibles en la performance de consultas del tipo: "digame qué datos tiene que lo busco" ya que con las condiciones adecuadas se pueden hacer coordinar los filtros con el orden de búsqueda.
Ejemplo 1
El siguiente es un ejemplo de una condición de filtro:
ClienteNombre LIKE &ClienteNombre
WHEN NOT null(&ClienteNombre);
ClienteCedula >= &ClienteCedula
WHEN NOT null( &ClienteCedula);
La forma de interpretar el código anterior es:
Si la variable &ClienteNombre tiene algún valor entonces GeneXus aplicará el filtro ClienteNombre LIKE &ClienteNombre. Si, además, la variable &ClienteCedula tiene algún valor también aplicará el filtro ClienteCédula >= &ClienteCedula en una relación de AND con los demás filtros.
Si ninguna variable tiene valor, entonces no se aplicará ningun filtro.
Ejemplo 2
For each ClienteNombre WHEN NOT null(&ClienteNombre)
Order ClienteCedula WHEN NOT null( &ClienteCedula)
...
Endfor
En este For Each, la navegación se realizará ordenada por ClienteNombre si la variable &ClienteNombre tiene un valor. Si no lo tiene, entonces el órden será por ClienteCédula si &ClienteCedula tiene un valor. En última instancia, si ninguna de las condiciones anteriores se cumple, la navegación se realizará en un orden indefinido.
For each ClienteNombre WHEN NOT null(&ClienteNombre)
Order ClienteCedula WHEN NOT null( &ClienteCedula)
Order ClienteId
...
Endfor
En este otro For Each del ejemplo, los órdenes de navegación son iguales a los del primero a excepción del caso en que ninguna de las Conditions se cumpla por existir un Order incondicional. La navegación se realiza por el Order incondicional en este caso.