Solo los convertidores de la primera subconsulta UNION se aplican al resultado.

Solo los convertidores de la primera subconsulta UNION se aplican al resultado.

jOOQ 3.15 introdujo el concepto de convertidor ad-hoc, un convertidor aplicado "ad-hoc" a una sola consulta. Utiliza los mismos mecanismos subyacentes que cualquier Converter que se adjunta al código generado para su uso en cada solicitud.

Aquí hay un ejemplo de un convertidor ad hoc de este tipo:

// Without the converter, assuming BOOK.ID is of type Field<Integer>
Result<Record1<Integer>> result =
ctx.select(BOOK.ID)
   .from(BOOK)
   .fetch();

// With the converter
Result<Record1<Long>> result =
ctx.select(BOOK.ID.convertFrom(i -> i.longValue()))
   .from(BOOK)
   .fetch();

Aunque hay otras formas de convertir tipos de datos, como usar CAST() O COERCE() expresiones, este enfoque adjunta una Converter al campo, que se llama justo después de leer el Integer valor JDBC ResultSet para hacer uno Long. Esta conversión se realiza en el lado del cliente. El RDBMS que ejecuta la consulta no lo sabe.

¡Este es un detalle importante! ¡El RDBMS no es consciente de esto!

Índice
  1. Precaución: uso de UNION
  2. Solución
    1. Así:

Precaución: uso de UNION

Recientemente se ha planteado un problema interesante (#14693) sobre problemas de seguimiento relacionados con el uso de tales convertidores ad hoc en un UNION. Por ejemplo, supongamos que se está ejecutando esta consulta:

Result<Record1<Integer>> result =
ctx.select(BOOK.ID)
   .from(BOOK)
   .union(
    select(AUTHOR.ID)
   .from(AUTHOR))
   .fetch();

Esto podría producir algo como:

|id |
|---|
|1  |
|2  |
|3  |
|4  |

Suponiendo que esté disponible BOOK.ID están [1, 2, 3, 4] y disponible AUTHOR.ID están [1, 2]EL UNION eliminará los duplicados.

¿Qué crees que sucederá si adjuntamos este convertidor ad-hoc solo al segundo UNION subconsulta?

Result<Record1<Integer>> result =
ctx.select(BOOK.ID)
   .from(BOOK)
   .union(
    select(AUTHOR.ID.convertFrom(i -> -i))
   .from(AUTHOR))
   .fetch();

Su propósito parece ser obtener el valor negativo de cada AUTHOR.IDmientras mantiene el BOOK.ID intacto. Pero recuerda:

  • La conversión ocurre en el cliente, no en el servidor, por lo que el RDBMS no lo sabe.
  • Esto significa que no tiene ningún efecto sobre el UNION operador
  • Además, jOOQ no sabe qué UNION la subconsulta contribuye con qué fila, por lo que no puede decidir si aplicar o no el convertidor.

Y eso es de hecho lo que está sucediendo. El resultado es siempre:

|id |
|---|
|1  |
|2  |
|3  |
|4  |

y la lambda i -> -i nunca se llama! Esto no solo es cierto para los convertidores ad hoc, sino también para cualquier otro Converter (O Binding) que adjunte a estas publicaciones proyectadas. jOOQ solo considerará el tipo de línea de la primera UNION subconsulta al recuperar resultados de un JDBC (o R2DBC) ResultSet. Solo tienes que garantizar que los dos tipos de línea sean compatibles para que el compilador de Java compruebe el tipo de tu consulta.

Solución

En realidad, solo hay 2 soluciones para tal situación:

  • Si está seguro de que su conversión debe ocurrir en su código de cliente (a diferencia del servidor), debe aplicarlo al menos al primero UNION subconsulta Idealmente, simplemente lo aplicaría a todos UNION subconsultas para mantener la coherencia, incluso en caso de que extraiga una subconsulta para reutilizarla.
  • Tal vez debería haber movido la conversión del lado del servidor, en primer lugar

En el último caso, esta consulta podría tener más sentido, si la intención fuera crear AUTHOR.ID valores:

Result<Record1<Integer>> result =
ctx.select(BOOK.ID)
   .from(BOOK)
   .union(
    select(AUTHOR.ID.neg())
   .from(AUTHOR))
   .fetch();

Esto ahora producirá la siguiente consulta SQL:

SELECT book.id
FROM book
UNION
SELECT -author.id
FROM author

Y un conjunto de resultados como este:

|id |
|---|
|-2 |
|-1 |
|1  |
|2  |
|3  |
|4  |

Tenga esto en cuenta cuando utilice convertidores ad hoc con MULTISET¡en particular!

Si quieres conocer otros artículos parecidos a Solo los convertidores de la primera subconsulta UNION se aplican al resultado. puedes visitar la categoría Código.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir

Esta página web utiliza cookies para analizar de forma anónima y estadística el uso que haces de la web, mejorar los contenidos y tu experiencia de navegación. Para más información accede a la Política de Cookies . Ver mas