Russian Qt Forum
Ноябрь 23, 2024, 18:06 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: [4.4.1] UNION и bindValue  (Прочитано 7345 раз)
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« : Сентябрь 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
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
developer
Гость
« Ответ #1 : Сентябрь 05, 2008, 13:37 »

Мне кажеться что UNION несколько устарелый запрос, лучше использовать JOIN-ы. Возможно тогда не будет проблем
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #2 : Сентябрь 05, 2008, 17:58 »

Да не важно что устарело, а что нет. Есть стандарт sql и его должны подерживать. Тут другой вопрос: кто прав?
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Alex03
Гость
« Ответ #3 : Сентябрь 07, 2008, 12:52 »

...
Это баг или фича?
...
Скорее фича. Улыбающийся

Записан
Alex03
Гость
« Ответ #4 : Сентябрь 07, 2008, 12:57 »

Мне кажеться что UNION несколько устарелый запрос, лучше использовать JOIN-ы. Возможно тогда не будет проблем
developer А приведите ка запрос с JOIN, функционально аналогичный запросу panter_dsd?
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #5 : Сентябрь 07, 2008, 15:07 »

...
Это баг или фича?
...
Скорее фича. Улыбающийся
Раз фича, то можешь хоть одно объяснение ей придумать? Что-то у меня не получается.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Tonal
Гость
« Ответ #6 : Сентябрь 07, 2008, 22:41 »

А ты на реализацию bindValue посмотри - там вроде всё прозрачно. Улыбающийся
Записан
Alex03
Гость
« Ответ #7 : Сентябрь 08, 2008, 05:46 »

Скорее фича. Улыбающийся
Раз фича, то можешь хоть одно объяснение ей придумать? Что-то у меня не получается.

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

Объяснения... проще реализация (небольшой выйгрыш по скорости/размеру кода), c Sql::Out две переменные в запросе с одним и тем же именем - считай ошибка проектирования.
Хотя конечно если б тролли добавили в код немного искусственного интелекта было бы не плохо. Улыбающийся
« Последнее редактирование: Сентябрь 08, 2008, 05:48 от Alex03 » Записан
Tonal
Гость
« Ответ #8 : Сентябрь 08, 2008, 07:50 »

Таки судя по всему баг.
Посмотрев на код QSqlResult::exec() можно заметить, что идёт тупая замена в строке запроса имён параметров на значения.
Находят первое вхождение параметра и заменяют. Если дописать 2 строчки, можно заменить все вхождения.

С другой стороны, должен выполнятся не QSqlResult::exec() а exec() соответствующего драйвера, но Firebird не поддерживает именованные параметры в запросах напрямую, так что разумно предположить, что где-то делается та же, или похожая, замена (кода с ходу не нашел)...
Записан
Alex03
Гость
« Ответ #9 : Сентябрь 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() делает то что нужно.
Записан
Tonal
Гость
« Ответ #10 : Сентябрь 08, 2008, 10:47 »

Это понятно. Ты можешь указать где там код, который отвечает за биндинг по имени?
Ведь Firebird его не поддерживает - значит Qt должно как-то его само обрабатывать.
Записан
Alex03
Гость
« Ответ #11 : Сентябрь 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();
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.095 секунд. Запросов: 22.