powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Firebird + Python = bullshit
40 сообщений из 40, показаны все 2 страниц
Firebird + Python = bullshit
    #39240547
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Приветствую всех! Столкнулся с одной проблемкой при работе с Firebird и с использованием библиотеки питоновской библиотеки fdb. Суть проблемы также описал на стэковерфлове . Продублирую это и здесь. Обратите внимание на код ниже:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
>>> import fdb
>>> cnx = fdb.connect(dsn = "C:\data\REESTR.FDB", user = "sysdba", password = "masterkey")
>>> cnx.begin()
>>> cursor = cnx.cursor()
>>> query = "SELECT CASE WHEN 'val_1' = 'val_1' THEN ? ELSE 'val_2' END AS TXT FROM TEST_TABLE"
>>> dat = ('val_1', )
>>> cursor.execute(query, dat) # с запросом выше все ок
<fdb.fbcore.Cursor object at 0x0000000002FEC978>
>>> # а теперь давайте поменяем чуток наш запрос
>>> query = "SELECT CASE WHEN 'val_1' = 'val_1' THEN ? ELSE ? END AS TXT FROM TEST_TABLE"
>>> dat = ('val_1', 'val_2', )
>>> cursor.execute(query, dat)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python34\lib\site-packages\fdb-1.6-py3.4.egg\fdb\fbcore.py", line 3573, in execute
  self._ps = PreparedStatement(operation, self, True)
  File "C:\Python34\lib\site-packages\fdb-1.6-py3.4.egg\fdb\fbcore.py", line 2182, in __init__
  "Error while preparing SQL statement:")
  fdb.fbcore.DatabaseError: ('Error while preparing SQL statement:\n- SQLCODE: -804\n- 
  Dynamic SQL Error\n- SQL error code = -804\n- 
  Data type unknown', -804, 335544569)



Обратите внимание, что все что поменялось - это еще одна подготовленная переменная (prepared variable) после слова ELSE в запросе. Причем, что странно Питон не ругается на аналогичную переменную поле ключевого слова THEN. В чем тут проблема и почему так происходит сам не смог разобраться. Рассчитываю на вашу помощь, форумчане. Мерси!
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240549
IBExpert
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В сервере сломался телепатический модуль и поэтому он не может угадать тип параметров. Делай явный CAST к нужному типу.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240551
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Это у вас такой тонкий юмор про телепатический модуль? Согласно по fdb документации никакого явного каста не нужно делать. Да и с точки зрения приложения - это самоубийство. Потому что одно дело везде использовать старые добрые ?, а другое проверять каждую переменную. Значит все-таки я был прав по поводу bullshit? Бага в fdb?
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240553
IBExpert
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это у меня такой толстый намек на то, что если из текста запроса совершенно непонятно, какого типа используемые в нем параметры, то надо искать способ их серверу сообщить.
Можешь не искать и продолжать считать, что отсутствие телепатических способностей - это баг.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240554
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А где логика в том, что

Код: sql
1.
THEN ? 



работает, а

Код: sql
1.
ELSE ?



не работает?
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240555
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну а по поводу того, что из запроса совершенно не понятно, какой тип используется. На мой взгляд это понятно из списка параметров, который используется при подготовке запроса:

Код: sql
1.
2.
('val_1', 'val_2', ) # Очевидно, что это строковые данные, а не числовые
(1, 2, ) # Очевидно, что тут числовые данные



Ну и к тому же документация именно об этом и говорит и не приводит случаев, когда подготовленный запрос должен сработать, а когда - нет.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240560
Ivan_Pisarevsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JacobianНа мой взгляд это понятноНа мой, например, взгляд совершенно непонятно.

более того, запихни в первом варианте в параметр строку подлиннее. Повеселело?
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240563
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: sql
1.
2.
3.
4.
5.
6.
7.
>>> query = "SELECT CASE WHEN 'abcdefghijklmnopqrstuvwxyz' = 'abcdefghijklmnopqrstuvwxyz' THEN ? ELSE 'abcdefghijklmnopqrstuvwxyz' END AS TXT FROM TEST_TABLE"
>>> dat = ('abcdefghijklmnopqrstuvwxyz', )
>>> cursor.execute(query, dat)
<fdb.fbcore.Cursor object at 0x0000000002FEC978>
>>> res = cursor.fetchall()
>>> print(res)
[('abcdefghijklmnopqrstuvwxyz',)]



Не вижу проблемы.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240564
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Со строкой в тысячу символов тоже все норм. Так что не вижу повода для веселья.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240565
IBExpert
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JacobianНу а по поводу того, что из запроса совершенно не понятно, какой тип используется. На мой взгляд это понятно из списка параметров, который используется при подготовке запроса:

Кому понятно-то? Питону? Ну, пусть поделится этой информацией с сервером, если умеет.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240566
IBExpert
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JacobianСо строкой в тысячу символов тоже все норм. Так что не вижу повода для веселья.

А так?

Код: python
1.
2.
>>> query = "SELECT CASE WHEN 'val_1' = 'val_1' THEN ? ELSE 'val_2' END AS TXT FROM TEST_TABLE"
>>> dat = ('val_1111111111111111111111111111111111111111111111111111111', )
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240567
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Тоже все в порядке:

Код: sql
1.
2.
3.
4.
5.
6.
7.
>>> query = "SELECT CASE WHEN 'val_1111111111111111111111111111111111111111111111111111111' = 'val_1111111111111111111111111111111111111111111111111111111' THEN ? ELSE 'val_1111111111111111111111111111111111111111111111111111111' END AS TXT FROM TEST_TABLE"
>>> dat = ('val_1111111111111111111111111111111111111111111111111111111', )
>>> cursor.execute(query, dat)
<fdb.fbcore.Cursor object at 0x0000000002FEC978>
>>> res = cursor.fetchall()
>>> print(res)
[('val_1111111111111111111111111111111111111111111111111111111',)]
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240568
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Минуту. Не то сделал.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240570
IBExpert
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JacobianТоже все в порядке:


А нефиг мой пример менять, выполняй как есть.
Хотя, ты, кажется, не свою проблему хочешь решить, а баг в сервере нарыть. Его там нет, но ты рой. Удачи.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240573
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
тип параметра в ELSE сервер может предположить по THEN. И наоборот тоже может. Но если и THEN и ELSE оба параметры, то телепатический локатор не способен справиться с задачей. Никакого бага тут нет.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240576
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вообще-то у меня такой цели нет. Можешь обратить внимание, что я не констатировал баг, а спрашивал баг ли это. Куда больше меня интересует причина того, что происходит именно так. Я смотрю документацию и вижу в ней одно, а вы даете совершенно другую рекомендацию, противоречащую документации. Вы всячески не обращаете внимание на то, что я даю ссылки на документацию. Вот не ссылка, а цитата:

автор
Parametrized statements

When SQL command you want to execute contains data values, you can either:

Embed them directly or via string formatting into command string, e.g.:

cur.execute("insert into the_table (a,b,c) values ('aardvark', 1, 0.1)")
# or
cur.execute("select * from the_table where col == 'aardvark'")
# or
cur.execute("insert into the_table (a,b,c) values ('%s', %i, %f)" % ('aardvark',1,0.1))
# or
cur.execute("select * from the_table where col == '%s'" % 'aardvark')

Use parameter marker (?) in command string in the slots where values are expected, then supply those values as Python list or tuple:

cur.execute("insert into the_table (a,b,c) values (?,?,?)", ('aardvark', 1, 0.1))
# or
cur.execute("select * from the_table where col == ?",('aardvark',))

While both methods have the same results, the second one (called parametrized) has several important advantages:

You don’t need to handle conversions from Python data types to strings.
FDB will handle all data type conversions (if necessary) from Python data types to Firebird ones, including None/NULL conversion and conversion from unicode to byte strings in encoding expected by server.
You may pass BLOB values as open file-like objects, and FDB will handle the transfer of BLOB value.
If you’ll pass exactly the same command string again to particular Cursor instance, it will be executed more efficiently (see section about Prepared Statements for details).

Parametrized statemets also have some limitations. Currently:

DATE, TIME and DATETIME values must be relevant datetime objects.
NUMERIC and DECIMAL values must be decimal objects.




Обращаю внимание на то, что the second one (called parametrized) has several important advantages и на то, что второй вариант имеет ряд ограничений, но ни одно из них не касается строк. Получается, что документация не актуальна на все сто? Если нет, как бы вы сформулировали в ней тот нюанс, о котором я задал вопрос и объяснили, ПОЧЕМУ в данном случае использование маркера ? не является предпочтительным. К настоящему моменту я просто не услышал солидного аргумента и объяснения (толстые намеки не в счет).
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240578
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Благодарю, dimitr! Теперь все встало на свои места. Хотя подобное поведение удручает, так как в MySQL, SQLite, Postgres, Oracle и MSSQL подобная параметризация запроса работает, как и ожидаешь. Ну и сам вывод типа параметра ELSE по THEN, вы уж меня извините, кроме как бредом я не назову. (IMHO, сугубо субъективно и естественно не претендует на какую-то истину)
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240579
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хотя минутку, dimitr. Как же такой алгоритм вывода типа параметра объясняет ошибку, которая вылетает на последнем примере IBExpert?
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240583
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
весь топик не читал, но предположу, что параметр отпрепарировался как CHAR(N), а ты пихаешь в него CHAR(N+X). Что нифига не влазит и генерит ошибку усечения. И это тоже не баг, хотя тоже может показаться непривычным.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240586
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Jacobianвывод типа параметра ELSE по THEN, вы уж меня извините, кроме как бредом я не назову
тут не буду спорить :-) Вот только единственная альтернатива - выдавать ошибку и вообще никак не работать.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240609
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Jacobianв MySQL, SQLite, Postgres, Oracle и MSSQL подобная параметризация запроса
работает, как и ожидаешь.
Вышеназванные сервера даже не пытаются определять тип параметра. Поэтому всё и "работает".
Но когда ты задашься вопросом "а какой тип совать в параметр и какого размера буфер под
него выделять?" всё станет совсем не радужно.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240615
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov Вышеназванные сервера даже не пытаются определять тип параметра.

Вообще-то это не так или во всяком случае не совсем или не всегда так. Если взять тот же Оракл, то он не то что будет пытаться определить тип параметра, но может сделать implicit cast, и выдать ошибку в случае, если типы не совпадают, как, например, в этом случае:

[code]

select id from test_table WHERE id = :id

[code]

Если id имеет тип NUMBER, а в качестве параметра передадите какую-нибудь строку, то Оракл попробует привести эту строку к NUMBER и выкинет соответственно ошибку.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240617
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JacobianЕсли id имеет тип NUMBER, а в качестве параметра передадите какую-нибудь
строку, то Оракл попробует привести эту строку к NUMBER и выкинет соответственно ошибку.

Повторяю медленно: ты не можешь получить от Оракула тип параметра запроса. Вообще. Никак.
Ты вынужден отдавать ему те данные, которые у тебя есть и так как они есть. И надеяться,
что сервер не дурак и сможет преобразовать их правильно. Что у него получается не каждый раз.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240622
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Еще раз медленно: в том примере, что я привел Оракул (цитата) "пытается определять тип параметра" как NUMBER и выдает ошибку, если в качестве параметра передается какая-нибудь строка. Аналогичный запрос например в MySQL и Postgres уже к ошибке не приводит, потому что они (цитата) "даже не пытаются определять тип параметра". Поэтому то, что ты сказал (в том смысле, как я это понял), не обобщается на все (цитата) "вышеназванные сервера". НО. Я не исключаю, что мог понять этот комментарий не так как следует, и для этого может потребоваться тогда расшифровать что значит (цитата) "получить от ... тип параметра запроса" - можно на примере того же Firebird. А вообще поднятая в топике проблема решена и требует дальнейших объяснений.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240624
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
*не требует.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240626
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JacobianОракул (цитата) "пытается определять тип параметра" как NUMBER и выдает
ошибку, если в качестве параметра передается какая-нибудь строка.
Между "определением требуемого типа параметра" и "приведением типа данных, что ему пришли,
к типу поля при непосредственном сравнении с полем" дистанция огромного размера.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240631
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
То есть в конструкции вида:

Код: sql
1.
2.
3.
4.
5.
CASE
WHEN ID = ? #1
THEN 'abc'
ELSE ?         #2
END



если, как вы говорите, соблюдать "дистанцию", то в первом случае Firebird просто попытается "привести" параметр к типу поля, а во втором случае попытается определить тип, например, исходя из того, что положили в THEN? А в других базах (том же Оракуле) в первом случае тоже будет просто сделано приведение типов, а во втором случае вообще никакого определения типа параметра не будет, так же как и в других вышеназванных серверах?
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240634
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Jacobianв конструкции вида
Ты же понимаешь, что в этой конструкции булевское выражение для проверки и выражение для
формирования результата это две совсем-совсем разные вещи?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240638
IBExpert
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А что, кстати, умные ораклы и иже с ними вернут как результат запроса

Код: plsql
1.
SELECT CASE WHEN COL1 = COL2 THEN ? ELSE ? END AS TXT FROM TEST_TABLE



Каков будет тип результата?
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240639
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IBExpertКаков будет тип результата?
Ставлю на VARCHAR2(4000).
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240641
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
@IBExpert. Запрос, что я привел в самом начале - это примерно в 20 раз упрощенная версия того запроса, который запускается у меня в одном из модульных тестов. Так вот в Оракле, как и в остальных РСУБД, за исключением Firebird, все отрабатывает так, как по крайней мере ожидаешь. Конкретно твой запрос не проверял.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240642
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JacobianКонкретно твой запрос не проверял.
Вообще-то это как раз конкретно твой запрос, из-за которого ты и начал истерить:

Jacobian>>> # а теперь давайте поменяем чуток наш запрос
Код: sql
1.
2.
>>> query = "SELECT CASE WHEN 'val_1' = 'val_1' THEN ? ELSE ? END AS TXT FROM 
TEST_TABLE"


Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240645
Alexander A. Sak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovIBExpertКаков будет тип результата?
Ставлю на VARCHAR2(4000).

Так точно.

В PG, кстати, будет примерно так же: TEXT.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240647
Alexander A. Sak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя, с Ораклом я наверное погорячился.
Из джавы работаю. Там если явно не установить значение, получишь Not all variables bound, так что все не так однозначно (с).
Да и в SQL*Plus вроде такое же наблюдалось.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240648
Jacobian
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Во-первых, я не истерил. Во-вторых

Код: sql
1.
COL1 = COL2



Это буквально не то же самое, что

Код: sql
1.
'val_1' = 'val_1'
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39240650
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JacobianВо-первых, я не истерил. Во-вторых
Во-первых, внимательно посмотри на сабж.
Во-вторых, сравнение не имеет значения, вся фишка в параметрах на всех ветках результата.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39241714
Фотография Tonal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Jacobian... в MySQL, SQLite, Postgres, Oracle и MSSQL подобная параметризация запроса работает, как и ожидаешь.
За "всю Одессу" а не скажу, то вот все драйвера Python для MySQL при параметризации просто подставляют значения в текст запроса и уже его отправляют на сервер. Т. е. с типами вовсе не парятся. :)
Что приводит к тому, что ожидаемого выигрыша в скорости при использовании запросов с параметрами ты не получишь.
Т. е. работают они не совсем "как и ожидалось". :)

Ну а в FDB можно напрямую вызвать подготовку запроса и у получившегося объекта запросить ожидаемые типы аргументов.
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39241723
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tonalвсе драйвера Python для MySQL при параметризации просто подставляют значения в
текст запроса
У них выбора нет. У мускуля в параметризованных запросах сидело столько багов, что проще
было считать, что их не существует в принципе.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39241745
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это в каких версиях? И как сейчас?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Firebird + Python = bullshit
    #39241823
Фотография Tonal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovУ них выбора нет. У мускуля в параметризованных запросах сидело столько багов, что проще
было считать, что их не существует в принципе.
Тем не менее в PHP драйвере mysqli есть честные параметризованные запросы. Что интересно, при привязке переменных типы нужно указываются явно. :)

Вполне возможно, что опциональное явное указание типов параметров было бы полезно и python-ическому FDB, если бы его можно организовать.
...
Рейтинг: 0 / 0
40 сообщений из 40, показаны все 2 страниц
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Firebird + Python = bullshit
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]