Russian Qt Forum

Qt => Базы данных => Тема начата: Пантер от Сентябрь 04, 2008, 16:45



Название: [4.4.1] UNION и bindValue
Отправлено: Пантер от Сентябрь 04, 2008, 16:45
Протр*CENSORED*ся сегодня с одним запросом. В общем вот его упрощенная форма:
Код:
SELECT id,pole1
FROM table1
WHERE id=:id
UNION
SELECT id,pole2
FROM table2
WHERE id=:id
Далее делаю bindValue(":id",value) и..... получаю какую-то лажу. Особо интересно то, что в IBExpert данный дапрос отлично отрабатывается.
За 4 часа экспериментов было выявлено, что если сделать:
Код:
SELECT id,pole1
FROM table1
WHERE id=:id
UNION
SELECT id,pole2
FROM table2
WHERE id=:id1
И далее
bindValue(":id",value)
bindValue(":id1",value)
Все работает как часы.
Это баг или фича?
БД=FireBerd
DRIVER=QIBASE


Название: Re: [4.4.1] UNION и bindValue
Отправлено: developer от Сентябрь 05, 2008, 13:37
Мне кажеться что UNION несколько устарелый запрос, лучше использовать JOIN-ы. Возможно тогда не будет проблем


Название: Re: [4.4.1] UNION и bindValue
Отправлено: Пантер от Сентябрь 05, 2008, 17:58
Да не важно что устарело, а что нет. Есть стандарт sql и его должны подерживать. Тут другой вопрос: кто прав?


Название: Re: [4.4.1] UNION и bindValue
Отправлено: Alex03 от Сентябрь 07, 2008, 12:52
...
Это баг или фича?
...
Скорее фича. :)



Название: Re: [4.4.1] UNION и bindValue
Отправлено: Alex03 от Сентябрь 07, 2008, 12:57
Мне кажеться что UNION несколько устарелый запрос, лучше использовать JOIN-ы. Возможно тогда не будет проблем
developer А приведите ка запрос с JOIN, функционально аналогичный запросу panter_dsd?


Название: Re: [4.4.1] UNION и bindValue
Отправлено: Пантер от Сентябрь 07, 2008, 15:07
...
Это баг или фича?
...
Скорее фича. :)
Раз фича, то можешь хоть одно объяснение ей придумать? Что-то у меня не получается.


Название: Re: [4.4.1] UNION и bindValue
Отправлено: Tonal от Сентябрь 07, 2008, 22:41
А ты на реализацию bindValue посмотри - там вроде всё прозрачно. :)


Название: Re: [4.4.1] UNION и bindValue
Отправлено: Alex03 от Сентябрь 08, 2008, 05:46
Скорее фича. :)
Раз фича, то можешь хоть одно объяснение ей придумать? Что-то у меня не получается.

фича -> feature -> особенность

Объяснения... проще реализация (небольшой выйгрыш по скорости/размеру кода), c Sql::Out две переменные в запросе с одним и тем же именем - считай ошибка проектирования.
Хотя конечно если б тролли добавили в код немного искусственного интелекта было бы не плохо. :)


Название: Re: [4.4.1] UNION и bindValue
Отправлено: Tonal от Сентябрь 08, 2008, 07:50
Таки судя по всему баг.
Посмотрев на код QSqlResult::exec() можно заметить, что идёт тупая замена в строке запроса имён параметров на значения.
Находят первое вхождение параметра и заменяют. Если дописать 2 строчки, можно заменить все вхождения.

С другой стороны, должен выполнятся не QSqlResult::exec() а exec() соответствующего драйвера, но Firebird не поддерживает именованные параметры в запросах напрямую, так что разумно предположить, что где-то делается та же, или похожая, замена (кода с ходу не нашел)...


Название: Re: [4.4.1] UNION и bindValue
Отправлено: Alex03 от Сентябрь 08, 2008, 08:45
Таки судя по всему баг.
Посмотрев на код QSqlResult::exec() можно заметить, что идёт тупая замена в строке запроса имён параметров на значения.
Находят первое вхождение параметра и заменяют. Если дописать 2 строчки, можно заменить все вхождения.

С другой стороны, должен выполнятся не QSqlResult::exec() а exec() соответствующего драйвера, но Firebird не поддерживает именованные параметры в запросах напрямую, так что разумно предположить, что где-то делается та же, или похожая, замена (кода с ходу не нашел)...
QSqlResult - абстрактный класс, и exec() в нём определён для СУБД не поддерживающих QSqlDriver::PreparedQueries.

В случае же с IB/FB имеем:
Код:
class Q_SQL_EXPORT QSqlCachedResult: public QSqlResult ...
class QIBaseResult : public QSqlCachedResult ...
Ну а QIBaseResult::exec() делает то что нужно.


Название: Re: [4.4.1] UNION и bindValue
Отправлено: Tonal от Сентябрь 08, 2008, 10:47
Это понятно. Ты можешь указать где там код, который отвечает за биндинг по имени?
Ведь Firebird его не поддерживает - значит Qt должно как-то его само обрабатывать.


Название: Re: [4.4.1] UNION и bindValue
Отправлено: Alex03 от Сентябрь 08, 2008, 12:20
Это понятно. Ты можешь указать где там код, который отвечает за биндинг по имени?
Ведь Firebird его не поддерживает - значит Qt должно как-то его само обрабатывать.

QSqlResult::BindValue()/addBindValue() строят в памяти соотношения имён/позиций со значениями.

bool QSqlResult::savePrepare(const QString& query) разруливает тот или иной способ задания параметров, модифицирует, если надо, текст запроса, изменяя :Var1 на ? и наоборот. Ну а в случае если драйвер не имеет QSqlDriver::PreparedQueries (или не переопределён prepare()), то вызывается дефолтный prepare(), который по сути готовит данные для дефолтного exec(), который в свою очередь подставляет в запрос непосредсдвенные значения переменных.

Драйвер-ы БД могут вызывать чтото из
Код:
QVariant QSqlResult::boundValue(int index) const
QVariant QSqlResult::boundValue(const QString& placeholder) const
QSql::ParamType QSqlResult::bindValueType(int index) const
QSql::ParamType QSqlResult::bindValueType(const QString& placeholder) const
int QSqlResult::boundValueCount() const
QVector<QVariant>& QSqlResult::boundValues() const

Как пример, в QIBaseResult::exec() вызывается boundValues();