Как получить более 1000 элементов в HSQLDB в операторе CASE WHEN? - PullRequest
1 голос
/ 13 января 2009

Я выполняю следующий запрос в гиперзвуковой базе данных (HSQLDB):

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

Когда число предложений «WHEN» превышает 1000, я получаю Java StackOverflowError, выдаваемый драйвером JDBC в org.hsqldb.jdbc.Util.sqlException().

Вот действительно странная часть: я попытался разбить мое заявление CASE на куски, например, 100 КОГДА пунктов, сопровождаемых ELSE ( CASE foo WHEN ... ) END. Но даже с этим переписыванием я получаю точно такое же поведение!

Я не вижу ссылки на ограничение 1000 или что-либо еще в руководстве по HSQLDB. Помогите!

Ответы [ 3 ]

1 голос
/ 13 января 2009

Полностью исключить оператор CASE.

Создайте таблицу, используя эти 1000 значений, затем просто выполните внутреннее соединение с этой таблицей.

1 голос
/ 13 января 2009

Как сказал Билл, невозможно удалить ограничение с учетом очевидного дизайна синтаксического анализатора HSQL.

С точки зрения смягчения ограничения (т. Е. Позволяя себе добраться до 1000 переключателей, просто увеличив предел до ... где-то более 1000), у вас есть два варианта.

  1. Увеличьте размер стека в виртуальной машине при запуске приложения. Если вы используете виртуальную машину Sun Hotspot, вы должны пройти, например, -XX: ThreadStackSize = 1024 для использования стека 1 МБ на поток вместо 512 КБ по умолчанию. Это может позволить вам достичь большей глубины рекурсии.
  2. Вы можете запустить свою работу в потоке, созданном конструктором Thread (ThreadGroup, Runnable, String, long), где последним параметром является запрошенный размер стека. Это может или не может работать; если вы читаете Javadoc, это предложение - виртуальные машины более чем рады игнорировать этот запрос. Не уверен, что именно делает Hotspot, но это может помочь.
1 голос
/ 13 января 2009

Вы никогда не должны приближаться к 1000 терминам в выражении CASE. Задолго до этого вы должны поместить другие значения в отдельную таблицу и выбрать их, присоединившись.

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 говорит о StackOverflowError:

Брошенный, когда переполнение стека происходит, потому что приложение рекурсивно слишком глубоко.

Так что я бы предположил, что когда HSQLDB анализирует выражение CASE, каждый член WHEN добавляет еще один слой в стек времени выполнения (на самом деле, вероятно, несколько слоев на WHEN).

Вероятно, вы получите похожее StackOverflowError, если у вас будет арифметическое выражение с 1000 уровнями вложенных скобок.

Предел 1000, вероятно, является переменной величиной, в зависимости от реализации виртуальной машины Java, версии Java, платформы, на которой вы работаете, объема доступной памяти и т. Д. Они могут не документироваться в документации HSQLDB. потому что это предел для конкретной платформы, а не что-то встроенное в HSQLDB.

...