powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Firebird + Python = bullshit
25 сообщений из 40, страница 1 из 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
25 сообщений из 40, страница 1 из 2
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Firebird + Python = bullshit
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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