Pregunta

Estoy ejecutando la siguiente consulta en Hypersonic DB (HSQLDB):

SELECT (CASE foo WHEN 'a' THEN 'bar' WHEN 'b' THEN 'biz' ....
        ELSE 'fin' END ) FROM MyTable LIMIT 1

Cuando el número de " CUANDO " Las cláusulas exceden aproximadamente 1000, obtengo un StackOverflowError de Java lanzado por el controlador JDBC en org.hsqldb.jdbc.Util.sqlException () .

Aquí está la parte realmente extraña: intenté romper mi declaración CASE en pedazos con p. ej. 100 cláusulas WHEN seguidas de ELSE (CASE foo WHEN ...) END . ¡Pero incluso con esta reescritura obtengo exactamente el mismo comportamiento!

No veo ninguna referencia a un límite de 1000 o cualquier otra cosa en el manual HSQLDB. Ayuda!

¿Fue útil?

Solución

Nunca debe acercarse a 1000 términos en una declaración CASE . Mucho antes de eso, debe colocar los otros valores en una tabla separada y elegirlos uniéndolos.

INSERT INTO MappingTable (foo, string) VALUES
  ('a', 'bar'), ('b', 'biz'), ...

SELECT COALESCE(m.string, 'fin')
FROM MyTable t LEFT OUTER JOIN MappingTable m USING (foo)
LIMIT 1;

Java API dice acerca de StackOverflowError:

  

Se produce cuando se produce un desbordamiento de la pila porque una aplicación se repite demasiado profundamente.

Entonces supongo que cuando HSQLDB analiza una expresión CASE , cada término WHEN agrega otra capa a la pila de tiempo de ejecución (en realidad, probablemente varias capas por WHEN ).

Probablemente obtendría un StackOverflowError similar si tuviera una expresión aritmética con 1,000 niveles de paréntesis anidados.

El límite de 1,000 es probablemente variable, dependiendo de la implementación de la máquina virtual de Java, la versión de Java, la plataforma en la que se está ejecutando, la cantidad de memoria disponible, etc. Es posible que no la documenten en la documentación de HSQLDB porque es un límite específico de la plataforma, no algo integrado en HSQLDB.

Otros consejos

Eliminar completamente la declaración CASE.

Haga una tabla usando esos 1000 valores, luego simplemente haga una unión interna a esa tabla.

Como dijo Bill, es imposible eliminar el límite dado el aparente diseño del analizador HSQL.

En términos de aliviar el límite (es decir, permitirse llegar a 1000 interruptores simplemente empujando el límite hasta ... en algún lugar por encima de 1000), tiene dos opciones.

  1. Aumente el tamaño de la pila en la VM cuando ejecute su aplicación. Si está utilizando Sun's Hotspot VM, debería poder pasar, p. -XX: ThreadStackSize = 1024 para usar una pila de 1 MB por hilo, en lugar de los 512K predeterminados. Eso puede permitirle llegar a una mayor profundidad de recursión.
  2. Puede ejecutar su trabajo en un Thread creado por el constructor Thread (ThreadGroup, Runnable, String, long), donde el último parámetro es un tamaño de pila solicitado. Esto puede o no funcionar; si lee el Javadoc, es una sugerencia: las máquinas virtuales son más que bienvenidas a ignorar esta solicitud. No estoy seguro de lo que Hotspot hace específicamente, pero podría ayudar.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top