Domanda

Sto eseguendo la seguente query in Hypersonic DB (HSQLDB):

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

Quando il numero di " QUANDO " le clausole superano circa 1000, ottengo un StackOverflowError Java lanciato dal driver JDBC in org.hsqldb.jdbc.Util.sqlException () .

Ecco la parte davvero strana: ho provato a spezzare la mia dichiarazione CASE in pezzi con es. 100 clausole WHEN seguite da ELSE (CASE foo WHEN ...) END . Ma anche con questa riscrittura ottengo esattamente lo stesso comportamento!

Non vedo alcun riferimento a un limite di 1000 o qualsiasi altra cosa nel manuale di HSQLDB. Aiuto!

È stato utile?

Soluzione

Non dovresti mai arrivare vicino a 1000 termini in un'istruzione CASE . Molto prima, dovresti mettere gli altri valori in una tabella separata e selezionarli unendo.

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;

L'API Java dice di StackOverflowError:

  

Generato quando si verifica un overflow dello stack perché un'applicazione esegue un ricorso troppo profondo.

Quindi immagino che quando HSQLDB analizza un'espressione CASE , ciascun termine WHEN aggiunge un altro layer allo stack di runtime (in realtà probabilmente diversi layer per WHEN ).

Probabilmente otterrai uno StackOverflowError simile se avessi un'espressione aritmetica con 1.000 livelli di parentesi annidate.

Il limite di 1.000 è probabilmente variabile, a seconda dell'implementazione della VM Java, della versione di Java, della piattaforma su cui si sta eseguendo, della quantità di memoria disponibile, ecc. Potrebbero non essere documentati nella documentazione HSQLDB perché è un limite specifico della piattaforma, non qualcosa incorporato in HSQLDB.

Altri suggerimenti

Elimina completamente l'istruzione CASE.

Crea una tabella usando quei 1000 valori, quindi fai un join interno a quella tabella.

Come ha detto Bill, è impossibile rimuovere il limite dato l'apparente design del parser HSQL.

In termini di alleviare il limite (ovvero lasciarti arrivare a 1000 interruttori semplicemente spingendo il limite fino a ... da qualche parte su 1000), hai due opzioni.

  1. Aumenta le dimensioni dello stack nella VM durante l'esecuzione dell'app. Se stai utilizzando l'Hotspot VM di Sun, dovresti essere in grado di passare ad es. -XX: ThreadStackSize = 1024 per utilizzare uno stack da 1 MB per thread, anziché i 512 KB predefiniti. Ciò potrebbe consentire di ottenere una maggiore profondità di ricorsione.
  2. Puoi eseguire il tuo lavoro in un thread creato dal costruttore Thread (ThreadGroup, Runnable, String, long), dove l'ultimo parametro è una dimensione dello stack richiesta. Questo può o non può funzionare; se leggi Javadoc, è un suggerimento: le VM sono più che benvenute nell'ignorare questa richiesta. Non sono sicuro di cosa faccia specificamente Hotspot, ma potrebbe aiutare.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top