Страница 1 из 2
Firebird + IBX: проблемы с timestamp и TDateTimeField
Добавлено: 28 авг 2006, 15:16
gvy
Перевожу программу, успешно проработавшую 5 лет под разными версиями InterBase, на Firebird 2.0 RC4.
Возникла проблема c типом timestamp и соответствующим ему TDateTimeField в программе.
1.Генерируется update SQL, в который в WHERE добавляются условия для полей, которые
изменились. Что-то наподобие:
update table_name
set timestamp_field = current_timestamp
where timestamp_field = :old_timestamp_field and ...;
2. При изменении в программе поля типа timestamp (через TDateTimeField) в Firebird этот update
не обновляет запись, получаю ошибку "Update failed".
3. Причина - функция current_timestamp в InterBase не возвращает доли секунды (всегда нули),
а в Firebird - возвращает. Кто не верит, выполните для обеих баз:
select cast( current_timestamp as varchar(32) ) from rdb$database;
Дальше, если посмотреть в логе, какой параметр реально подставляется при выполнении вместо
:old_timestamp_field, то увидим, что это дата + время, без долей секунд, т.к. TDateTimeField их
и не должен содержать.
Вот и получается, если в базе timestamp уже с долями секунды, то условие
timestamp_field = :old_timestamp_field эту запись не выберет.
Что по этому поводу скажут специалисты?
P.S. Попытка вместо TDateTimeField использовать TSQLTimeStampField не увенчалась успехом,
т.к. IBX говорит, что ожидал SQLTimeStamp, а реально получил DateTime.
Добавлено: 28 авг 2006, 15:24
Dimitry Sibiryakov
IBX вообще не умеет работать со временем точнее секунды. Выбросить его нафиг.
Добавлено: 28 авг 2006, 15:29
gvy
Я бы так и сделал, но нету ни времени, ни желания кардинально менять старую отлаженную программу, и за это никто не даст денег. Жду ответов по существу.
Добавлено: 28 авг 2006, 15:36
Merlin
gvy писал(а):Я бы так и сделал, но нету ни времени, ни желания кардинально менять старую отлаженную программу, и за это никто не даст денег. Жду ответов по существу.
Тогда закатывай рукава, бери напильник и обработай им IBX. По этим долям секунды широкие массы дружно страдали много лет и наконец-то выпросили. Ты попал в категорию, которая "попала". Такая категория всегда бывает, к сожалению.
Добавлено: 28 авг 2006, 15:37
kdv
варианты
1. оставить программу на версии FB, в которой current_timestamp не возвращает миллисекунды
2. попробовать использовать cast('now' as timestamp)
Добавлено: 28 авг 2006, 15:48
Dimitry Sibiryakov
gvy писал(а):Жду ответов по существу.
Тогда у тебя есть небогатый выбор:
- Доступаться к sqlvar напрямую (как это делаю я)
Переписать работу AsDateTime
Передавать строку.
Добавлено: 28 авг 2006, 15:49
gvy
Ясно. Просто интересно, автор IBX вообще ещё поддерживает своё творение? Что-то с момента выхода IBX 6.08 прошло слишком много времени. И где ему пожаловаться, существует в природе официальный сайт IВX?
Добавлено: 28 авг 2006, 15:52
kdv
кстати, IBX тут на первый взгляд ни при чем. стандартные типы столбцов описаны в DB.PAS.
вполне может кончится тем, что current_timestamp вернут обратно, и сделают current_timestampms или что-то вроде.
Добавлено: 28 авг 2006, 15:57
Dimitry Sibiryakov
А на второй взгляд становится ясно, что миллисекунды отпадают при использовании isc_encode/decode_date() в методах Get/SetAsDateTime.
Добавлено: 28 авг 2006, 15:59
kdv
Что-то с момента выхода IBX 6.08 прошло слишком много времени.
изменения только вместе с новыми версиями дельфей. Политика вполне понятная.
официального сайта ibx не существует, т.к. ibx это часть софта Borland. То есть, официальный сайт IBX тут:
http://codecentral.borland.com/Author.aspx?ID=102
добавлю, что в IBX для D2006 в плане timestamp вроде бы все то же самое.
Добавлено: 28 авг 2006, 16:06
gvy
Я как раз и делаю это в C++ Builder 2006.
Добавлено: 28 авг 2006, 16:12
kdv
в общем, если не нужны миллисекунды - резать в триггере или в запросе, при помощи самописной udf.
с now та же история - то есть, миллисекунды теперь везде. Вот же ж блин, благими намерениями...
Причем, на fb2 таким образом перестанут работать все приложения, которые работают в IBX (как минимум. Бузаджи сейчас FIBPlus проверяет на эту тему) и других драйверах, которые миллисекунды в timestamp не учитывают (по разным причинам).
так что я за возврат старой функциональности и введение нестандартного current_timestampmsec
Добавлено: 28 авг 2006, 16:19
dimitr
кому нужен timestamp без секунд - пусть юзает current_timestamp(0), возможность таковая есть. А если IBX до сих пор не умеет работать с миллисекундами во времени - это их проблемы, IB это поддерживает уже лет 15 как.
Добавлено: 28 авг 2006, 16:32
kdv
продолжаем. стандартные функции форматирования даты-времени в дельфях могут показать миллисекунды, если указать формат
hh:mm:ss.zzz
только вот 3 цифры под миллисекунды, и все. если написать zzzz - все равно 3 цифры выводится.
Добавлено: 28 авг 2006, 16:40
kdv
кстати, о птичках. существующие 15 лет в IB миллисекунды - не миллисекунды, а десятые миллисекунд. Потому что миллисекунды, это 0.nnn. Я не знаю, как дело с форматированием времени в других языках, поэтому прошу прокомментировать.
то есть, я не знаю, как стандартными средствами в Delphi ввести или вывести десятые миллисекунды. StrToDateTime работает в пределах стандартного формата миллисекунд - zzz.
p.s. что IBX миллисекунды обрезает - это уже другой вопрос.
Добавлено: 28 авг 2006, 17:10
gvy
Да, current_timestamp(0) решает проблему. Но всё равно все старые приложения придётся переделывать. Не очень хорошо. Вот он, призрак обратной совместимости

Добавлено: 28 авг 2006, 17:14
Merlin
Ну, положим, не все, а работавшие вопреки здравому смыслу, используя старинную багу...
Добавлено: 28 авг 2006, 17:23
gvy
Ключевое слово тут было "работавшие"

Ладно, посмотрим, что на это скажут разработчики сервера.
Добавлено: 28 авг 2006, 17:31
kdv
разработчик уже сказал. под FB2 переделывать на current_timestamp(0). или ты имел в виду разработчиков приложений?
to Merlin: я к тому, что миллисекунды это не 0.nnnn, а 0.nnn. То есть даже то что в IB было 15 лет, все равно "не соответствует".
Добавлено: 28 авг 2006, 17:46
buzz
В общем FIBplus работает как положено и ничего не теряется. Вопрошавшему же посоветую повесить на эту несчастную таблицу триггер, который через
current_timestamp(0) просто занулит ненужные вам доли секунды.