Groovy y los alias de columna en SQL
Groovy trae “de serie” soporte para interactuar con bases de datos SQL. Ese soporte descansa sobre las librerías java, y en este caso sobre JDBC. De esa manera consigues la fiabilidad y robustez de JDBC, o al menos de algunos drivers JDBC, y la expresividad y “user-friendliness” de groovy, consiguiendo cosas como ésta:
db.rows("select * from users").each { println it.name }
Cada registro que devuelve groovy es de hecho un map, cuyas claves son los nombres de los campos de la query. Es un ejemplo estupendo del principio DRY: si ya has definido cómo se llaman tus columnas en la tabla, no vuelvas a especificarlo en el código que accede a la tabla.
Por desgracia casi nunca quieres la lista de nombres de la tabla usuario. Lo normal es que quieras cosas más complejas de calcular, es frecuente que quieras que tu select devuelva campos calculados:
SELECT avg(age), COUNT(id) FROM users
Y groovy ejecuta eso sin problemas, pero no te deja acceder a los resultados de tu query, de hecho lo que hace, de forma bastante torpe, es considerar que las columnas que devuelve tu select se llaman “” (cadena vacía). Para cada fila-map que devuelve tu query, groovy debe hacer algo parecido a:
m.put(columna, valor)
De forma que si todas las columnas se llaman igual, acabas con un map de un solo elemento. La solución más directa es usar alias:
SELECT avg(age) AS edad, COUNT(id) AS numero FROM users
Pero el resultado es el mismo. Un poquillo de Google y llegas a una issue del jira de groovy. Alguien se queja de esto y le responden que es comportamiento esperado de JDBC, pero parece que ellos hablan de los alias en las tablas, no en las columnas. Groovy proporciona otras formas de hacer queries más cercanas a JDBC, cosas como obtener un resultSet e iterarlo. Pero para los scripts encuentro particularmente útil la forma antes descrita.
Sin más preámbulo la cutre-solución: envuelve la query en una super-query, de esa forma “engañas” a groovy, haciéndole pensar que los nombres de tus columnas son los alias que le has pasado:
SELECT * FROM (SELECT avg(age) AS edad, COUNT(id) AS numero FROM users) AS q
En su contexto grooviero quedaría así:
db.rows("select * from (select avg(age) as edad, count(id) as numero from users) as q").each { println it.edad println it.numero }
Miel sobre hojuelas :)
Tags: groovy sql alias ñapa
No hay comentarios
Comments RSS
TrackBack Identifier URI
No comments. Be the first.
Deja un comentario

