LINUX.ORG.RU

QSqlDatabase + QThread + вопрос

 , ,


0

2

Коллеги,

А что возвращать из функции, осуществляющей запрос к БД, выполняющийся в отдельном потоке?

Сейчас возвращаю QSqlQuery. Правильно ли это?

// синхронный запрос
Q_SLOT QSqlQuery querySync( const QString& query, bool* error = NULL );
// синхронный запрос с транзакцией
Q_SLOT QSqlQuery querySyncTrans( const QString& query, bool* error = NULL );
★★

А зачем тебе отдельный поток? Если я правильно понял у тебя

querySync();
querySyncTrans();
блокирующие же?

matrixd
()
Ответ на: комментарий от matrixd

Да, это блокирующие варианты - если результат нужен здесь и сейчас. Будут ещё и неблокирующие, возвращающие, QFuture. Но сейчас мне нужно понять, что именно возвращать в качестве результата..

i82 ★★
() автор топика
Ответ на: комментарий от neversleep

А что будет эффективнее в данном случае - возвращать QSqlQuery с его копированием, или же возвращать указатель на объект, создаваемый через new ?

i82 ★★
() автор топика
Ответ на: комментарий от trex6

Это в асинхронном случае? Возможно. Но что более правильно возвращать - QSqlQuery или QSqlResult? На сколько я вижу, QSqlQuery имеет метод `const QSqlResult* QSqlQuery::result()` и, кажется, при возвращении укзателя на QSqlResult, его придётся целиком скопировать... Или ошибаюсь?

i82 ★★
() автор топика
Ответ на: комментарий от i82

Если возвращаете указатель - скопируется только указатель, он по размерам маленький.

Правильнее возвращаеть QSqlQuery. У вас ведь код выполняет запрос, значит должен вернуть ответ. Если код запрос только конструирует, но не выполняет, тогда, естественно, возвращаете сам запрос.

trex6 ★★★★★
()
Последнее исправление: trex6 (всего исправлений: 1)
Ответ на: комментарий от i82

Тебе лучше или QSqlResult целиком копировать, не пологайся на указтель, или QSqlQuery. Мне лень читать исходники, но этот QSqlResult наверняка внутри QSqlQuery лежит. Сдохнет QSqlQuery до обращения к QSqlResult по указателю - огребешь сегфолт.

И всетаки, зачем тебе все это? Если ты тупо коммитишь в бд изменения то тебе должно хватить bool, если делаешь всякие селекты: возвращай QSqlQuery, емнип из QSqlResult данные не достанешь.

По уму все ошибки и т.д. должен обрабатывать твой класс для работы с базой данных. Ну или емитить сигналы при ошибках. А для синхронной работы с базой данных - или обрабатывай каждый запрос внутри класса и в нем же обрабатывай и ошибки, или же используй уже готовые классы.

matrixd
()

Может быть есть вариант использовать асинхронный api для работы с БД например для postgreSQL есть возможность так работать через libpq (можно написать нормальные prepare и insert без перевода строки в число). Как вариант можно еще использовать различные соединения для разных потоков.

ussr
()
Ответ на: комментарий от i82

Ну так если у QFuture сразу попросить результат, то операция станет вполне себе синхронной. Его и возвращай, пусть вызывающий код думает, нужен ему синхронный или асинхронный вариант.

Gorthauer ★★★★★
()
Ответ на: комментарий от Gorthauer

Именно. В итоге, так и сделал.

i82 ★★
() автор топика
Ответ на: комментарий от ussr

Это слишком низкий уровень, не хочется решая одну задачу, решать совсем другую ;)

i82 ★★
() автор топика

Как сделал

В общем, для тех, кому интересно. Работу с БД осуществляю через QtConcurrent::run(). Соответственно, возвращаемым результатом является QFuture<QSqlQuery>, который потом либо ожидается к завершению (это вариант - «синхронных» запросов), либо отслеживается через QFutureWatcher<QSqlQuery> с сигнализацией о завершении через сигнал.

Есть один момент. Так как заранее неизвестно, в каком из потоков (QThread) будет выполняться QtConcurrent::run(), то для каждого из потоков поддерживается свой экземпляр QSqlDatabase (в реализации - это QMap<QThread*, QSqlDatabase>).

Всем сапасибо.

i82 ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.