Pergunta

Estou executando a seguinte consulta em db hipersônico (HSQLDB):

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

Quando o número de cláusulas "quando" excede cerca de 1000, eu recebo um java StackOverflowError jogado pelo motorista JDBC em org.hsqldb.jdbc.Util.sqlException().

Aqui está a parte realmente estranha: tentei quebrar meu CASE declaração em pedaços com por exemplo, 100 quando cláusulas seguidas por ELSE ( CASE foo WHEN ... ) END. Mas mesmo com esta reescrita eu recebo exatamente O mesmo comportamento!

Não vejo nenhuma referência a um limite de 1000 ou qualquer outra coisa no manual do HSQLDB. Ajuda!

Foi útil?

Solução

Você nunca deve chegar a um lugar perto de 1000 termos em um CASE declaração. Muito antes disso, você deve colocar os outros valores em uma tabela separada e escolhê -los juntando -se.

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 diz sobre StackOverflowerRor:

Jogado quando um transbordamento de pilha ocorre porque um aplicativo é reduzido muito profundamente.

Então, eu acho que quando o hsqldb passa um CASE expressão, cada um WHEN O termo adiciona outra camada à pilha de tempo de execução (na verdade provavelmente várias camadas por WHEN).

Você provavelmente obteria um StackOverflowerRor semelhante se tivesse uma expressão aritmética com 1.000 níveis de parênteses aninhados.

O limite de 1.000 é provavelmente variável, dependendo da implementação da VM Java, a versão do Java, a plataforma em que você está executando, a quantidade de memória disponível etc. Eles podem não documentar na documentação do HSQLDB porque é um Limite específico da plataforma, não algo incorporado no HSQLDB.

Outras dicas

Elimine completamente a declaração do caso.

Faça uma tabela usando esses 1000 valores e basta fazer uma união interna para essa tabela.

Como Bill disse, é impossível remover O limite, dado o aparente design do analisador HSQL.

Em termos de aliviar o limite (ou seja, deixando -se chegar a 1000 interruptores apenas pressionando o limite até ... em algum lugar mais de 1000), você tem duas opções.

  1. Aumente o tamanho da pilha na VM ao executar seu aplicativo. Se você estiver usando o Hotspot VM da Sun, poderá passar por EG -xx: ThreadStackSize = 1024 para usar uma pilha de 1 MB por thread, em vez do 512K padrão. Isso pode permitir que você chegue a uma maior profundidade de recursão.
  2. Você pode executar seu trabalho em um encadeamento criado pelo Thread do construtor (ThreadGroup, Runnable, String, Long), onde o último parâmetro é um tamanho de pilha solicitado. Isso pode ou não funcionar; Se você ler o Javadoc, é uma sugestão - as VMs são mais do que bem -vindas a ignorar essa solicitação. Não tenho certeza do que o hotspot faz especificamente, mas pode ajudar.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top