Ищу готовую обёртку для QSqlDatabase или помощь в создании

heleo
Дата: 26.11.2014 20:39:36
Доброго времени суток.

В новом проекте появилась потребность в организации подключения к БД в отдельном потоке с возможностью использования оной в множестве других потоков.

Раньше данную задачу решали создание обертки работающий через сигналы и слоты с БД в другом потоке (либо без потока), но при этом не было потребностей организовывать доступ к одному конекту БД сразу из нескольких потоков.
Сейчас появилась потребность в переработке (написания с нуля) такой обертки которая позволит реализовать многопоточную работу с БД. При этом главным условием является использование только одного коннекта к БД без возможности создания множественных коннектов с теми же параметрами.
Следовательно возник вопрос: а нет ли уже готовых решений которые можно позаимствовать? Ну или может подскажете каким образом это проще реализовать для Qt?)

Заранее спасибо.
White Owl
Дата: 26.11.2014 23:31:39
Готовых не знаю.
Но в принципе, если у вас уже есть фоновый объект работающий через сигналы, то достаточно обернуть его в еще один фоновый объект который будет заниматься очередью запросов.
heleo
Дата: 27.11.2014 09:57:25
White Owl,

Это первое, что пришло в голову. Но к сожалению такие обертки усложняют использование базового функционала QSqlQuery, по факту нужно написать аналог bind и bound.
rovan
Дата: 27.11.2014 14:59:39
heleo,
Готового не знаю, увы.
Доводилось руками делать нечто подобное.
Можно скооперироваться, если есть желание.
Мыло открыто, пиши.
heleo
Дата: 27.11.2014 21:41:38
rovan,

Спасибо за предложение. Но пока что поищу дальше, может чего нарыть получится.
White Owl
Дата: 28.11.2014 01:55:07
heleo
Но к сожалению такие обертки усложняют использование базового функционала QSqlQuery, по факту нужно написать аналог bind и bound.
Вовсе нет.
Можно и без врапперов...

У тебя уже есть фоновая работа с БД? Как она организована?
Рабочий поток посылает в фоновый поток коннекта сообщение с sql запросом. Фоновый поток этот запрос отдает интерфейсному драйверу который и работает напрямую с СУБД. Дожидается ответа от этого интерфейсного драйвера и кидает рабочему потоку сигнал "готово". Потом по отдельному запросу отдает рабочему потоку резалтсет.
Так?

Теперь тебе достаточно в этот фоновый поток коннекта добавить индексированную очередь запросов. Тогда множество рабочих потоков смогут кидать запросы и получать в ответ индексы. Теперь объект работающий с СУБД может по очереди брать запросы из очереди, отправлять их в СУБД, а получив ответ ... Ну дальше уже варианты:
- кидать сигнал "готово" именно тому потоку который послал запрос (тогда при постановке запроса в очередь надо запоминать кто его послал).
- кидать широковещательный сигнал о готовности с добавлением в сигнал индекса. И рабочие потоки будут смотреть: мой индекс или не мой? Если мой - запрашивать резалтсет.
MasterZiv
Дата: 28.11.2014 13:21:55
Ещё раз, переосмыслим...

heleo

В новом проекте появилась потребность в организации подключения к БД в отдельном потоке



Именно подключаться к БД в отдельном потоке бессмысленно, это быстро, делается один раз -- можно сделать это в главном потоке.
(main)

heleo
с возможностью использования оной в множестве других потоков.


Это уже более осмысленно, но соединение на время выполнения запроса всё равно будет занято, поэтому особенно эффективно разделять его не получится.

Лучше (на мой взглад) делать компоненту "пул соединений и очередь запросов на асинхронное выполнение в БД"

heleo
Сейчас появилась потребность в переработке (написания с нуля) такой обертки которая позволит реализовать многопоточную работу с БД. При этом главным условием является использование только одного коннекта к БД без возможности создания множественных коннектов с теми же параметрами.


Это какое-то странное условие. По коннекту на запрос создавать, конечно, глупо, но 5-10 коннектов вместо одного -- вовсе нет ничего страшного.
heleo
Дата: 28.11.2014 22:58:31
Ага, так и сделано, только основной поток он же GUI не сигнал ждет, а просто включает новый цикл обработки событий и холостит до сигнала завершения запроса.

White Owl
heleo
Но к сожалению такие обертки усложняют использование базового функционала QSqlQuery, по факту нужно написать аналог bind и bound.
Вовсе нет.
Можно и без врапперов...

У тебя уже есть фоновая работа с БД? Как она организована?
Рабочий поток посылает в фоновый поток коннекта сообщение с sql запросом. Фоновый поток этот запрос отдает интерфейсному драйверу который и работает напрямую с СУБД. Дожидается ответа от этого интерфейсного драйвера и кидает рабочему потоку сигнал "готово". Потом по отдельному запросу отдает рабочему потоку резалтсет.
Так?

Теперь тебе достаточно в этот фоновый поток коннекта добавить индексированную очередь запросов. Тогда множество рабочих потоков смогут кидать запросы и получать в ответ индексы. Теперь объект работающий с СУБД может по очереди брать запросы из очереди, отправлять их в СУБД, а получив ответ ... Ну дальше уже варианты:
- кидать сигнал "готово" именно тому потоку который послал запрос (тогда при постановке запроса в очередь надо запоминать кто его послал).
- кидать широковещательный сигнал о готовности с добавлением в сигнал индекса. И рабочие потоки будут смотреть: мой индекс или не мой? Если мой - запрашивать резалтсет.


Это все хорошо до тех пор пока не появляется транзакция с begin, end и кучей запросов посередине в рамках работы одного из потоков, а следовательно тут не просто пул запросов и ответов по сигналам.
heleo
Дата: 28.11.2014 23:02:05
MasterZiv
Ещё раз, переосмыслим...

heleo
В новом проекте появилась потребность в организации подключения к БД в отдельном потоке



Именно подключаться к БД в отдельном потоке бессмысленно, это быстро, делается один раз -- можно сделать это в главном потоке.
(main)

heleo
с возможностью использования оной в множестве других потоков.


Это уже более осмысленно, но соединение на время выполнения запроса всё равно будет занято, поэтому особенно эффективно разделять его не получится.

Лучше (на мой взглад) делать компоненту "пул соединений и очередь запросов на асинхронное выполнение в БД"

heleo
Сейчас появилась потребность в переработке (написания с нуля) такой обертки которая позволит реализовать многопоточную работу с БД. При этом главным условием является использование только одного коннекта к БД без возможности создания множественных коннектов с теми же параметрами.


Это какое-то странное условие. По коннекту на запрос создавать, конечно, глупо, но 5-10 коннектов вместо одного -- вовсе нет ничего страшного.


Ну тут по всей видимости я криво отписался. Конечно конект один на все время работы программы, создание нескольких конектов под одними и теми же параметрами login\password не допускается. Создается он по факту в main путем создания отдельного потока с БД.
rovan
Дата: 03.12.2014 08:22:41
heleo, ну как, нашел что-нибудь?