Конференция "Базы" » Наткнулся на любопытное поведение TIBSQL [FireBird 2.1]
 
  • Ega23 © (24.01.12 16:17) [0]
    Есть генератор, есть таблица.
    На клиенте есть read-write транзакция + TIBSQL
    Задача - вставить запись в таблицу и получить значение.
    Код (условный):

    with TIBSQL.Create do
     try
       StartRWTran;
       try
          SQL.Text := 'insert into ttt (id) values (gen_id(ggg, 1)) returning id';
          ExecQuery;
          if not Eof
            ShowMessage(FieldByName('id').AsString);
          Commit;
       except
          Rollback;
       end;
     finally
       Free;
     end;



    Так вот. Не работает. Но, как только убираем строчку if not Eof - получаем сообщение с правильным id.

    Вопрос: как же так?
  • Cobalt © (24.01.12 16:21) [1]
    А если поставить не ShowMessage, а Application.ProcessMessages;?

    И вообще? что за странная привычка пользоваться ShowMessage?
    Скидывайте данные в лог/Label/Memo/Edit
  • turbouser © (24.01.12 16:21) [2]
    if not Eof and not Bof
    Когда-то наступал на эти грабли
  • Ega23 © (24.01.12 16:33) [3]

    > И вообще? что за странная привычка пользоваться ShowMessage?


    Вов, ну естественно там не ShowMessage, это я так, для наглядности.
  • Германн © (24.01.12 17:58) [4]

    > Наткнулся на любопытное поведение TIBSQL

    Если б мой заказчик не потерялся, я б тебя на эту фишку наткнул бы дней на десять ранее. :)
  • sniknik © (24.01.12 21:31) [5]
    а поставить First; перед условием?
    это может не от if not Eof, а от ExecQuery зависит, ведь не Open, же. (и кстати а если он?)

    тут, имхо, та же фигня почему не люблю,  AdoQuery, ясности нет.
  • Cobalt © (24.01.12 22:43) [6]
    Кстати, да, если после ExecQuery поставить First - отрабатывает правильно?
  • Германн © (25.01.12 01:53) [7]

    > sniknik ©   (24.01.12 21:31) [5]
    >
    > а поставить First; перед условием?
    > это может не от if not Eof, а от ExecQuery зависит, ведь
    > не Open, же. (и кстати а если он?)

    Метода Open у TIBSQL нет. (Сей компонент не является наследником TDataSet). Есть только свойство Open типа Boolean, но оно ReadOnly.
    Имхо сей компонент предназначен только для DML-запросов. Правда на Select запросы он не ругается и даже порой работает. Даже в ситуации описанной Олегом. А порой не работает. И х.з. почему.
    P.S. Сам работал с этим компонентом на Д2007.
  • Ega23 © (25.01.12 02:34) [8]

    > Имхо сей компонент предназначен только для DML-запросов.
    >  Правда на Select запросы он не ругается и даже порой работает.


    А Select - не DML?
    DDL-запросы не пробовал, но оно мне и не надо.


    > тут, имхо, та же фигня почему не люблю,  AdoQuery, ясности  нет.


    Эта штука, скорее, некий аналог ADOCommand. С неким recordSet, который совсем не TDataSet. Но всякие Next, Eof, FieldByName - сохранены.
  • Германн © (25.01.12 02:42) [9]

    > Ega23 ©   (25.01.12 02:34) [8]
    >
    >
    > > Имхо сей компонент предназначен только для DML-запросов.
    >
    > >  Правда на Select запросы он не ругается и даже порой
    > работает.
    >
    >
    > А Select - не DML?

    А хрен его знает. Не люблю менагеров! :)
  • Германн © (25.01.12 02:56) [10]

    > Ega23 ©   (25.01.12 02:34) [8]
    >
    >
    > > Имхо сей компонент предназначен только для DML-запросов.
    >
    > >  Правда на Select запросы он не ругается и даже порой
    > работает.
    >
    >
    > А Select - не DML?

    Ну да.
    Вот когда ткнут тебя мордой в ..., сразу вспоминаешь основы. Но только в том месте морды "которой ткнули".
    А каким термином отличаются запросы на изменение от запросов на чтение?
  • sniknik © (25.01.12 07:44) [11]
    > Но всякие Next, Eof, FieldByName - сохранены.
    ну так как тогда насчет First; перед условием?
  • Ega23 © (25.01.12 08:50) [12]

    > ну так как тогда насчет First; перед условием?


    Я проверю, просто не до этого сейчас.


    > А каким термином отличаются запросы на изменение от запросов
    > на чтение?


    Запрос в [0] - это на чтение или на изменение? А если я ХП-шку дёргаю, которая сначала чё-та удаляет, потом что-то апдейтит, а потом селект огроменный выдаёт?
    ИМХО, тут грань слишком тонка. Их как-то можно выделить в группы "возвращающая набор данных" и "не возвращающая набор данных". А уж что они там внутре из себя представляют - клиенту фиолетово.
  • Виталий Панасенко (26.01.12 11:23) [13]
    Юзай FIB+..Это не реклама..купил, доволен. IBX отдыхают, разве что самому на РЕАКТОР заточить
  • Ega23 © (26.01.12 13:07) [14]

    > .купил, доволен.


    Назови хотя бы одну объективную причину (а лучше - несколько) перехода со стандартных IB на FIB+?
    При условии, что у меня нет ни одного DB-Aware компонента, нет ни одного TDataSource, и повсеместно ORM используется.
  • Виталий Панасенко (26.01.12 13:46) [15]
    Boolean поля в Interbase 7 их отсутствие в FB...Где-то что-то не так...:)
  • Виталий Панасенко (26.01.12 13:50) [16]
    Я о закладке Interbase и FireBird. Тот же SET TERM (Отсуствующий у IB кажись с "семерки")
  • Ega23 © (26.01.12 14:30) [17]

    > Boolean поля в Interbase 7 их отсутствие в FB...Где-то что-
    > то не так...:)


    create domain TBoolean as smallint not null check ((value = 0) or (value = 1));



    Не вижу никаких проблем.
  • Виталий Панасенко (26.01.12 15:27) [18]
    ну да.. это все равно что на светлобежевое говорить что оно белое..оно то примерно так...но разница есть. я не знал, что IBX ведут себя как FIB+(я о булевых полях)
  • Ega23 © (26.01.12 16:47) [19]

    > ну да.. это все равно что на светлобежевое говорить что
    > оно белое..оно то примерно так.


    Давай разберёмся.
    В некоторых диалектах SQL (TSQL, например), есть тип bit. Фактически - 0 или 1. Причём, если у тебя в таблице 8 полей типа bit, то фактически эти 8 полей представляют из себя 1 байт (с битовой маской).
    Это всё замечательно, пока не возникает троичная логика True/False/NULL.
    Тут уже битом ну никак не обойтись.
    Отсюда возникает вопрос: насколько так сильно необходим данный тип, если ты не можешь им пользоваться в полной мере?

    Признаться, меня гораздо больше напрягает отсутствие типа byte, т.к. минимальным является smallint, а также явное отсутствие типа GUID (хотя Romkin говорил, что решаемо через collation. Но всё равно, хотелось бы автоматически).

    Также вызывает некоторое недоумение (не напрягает абсолютно, но недоумение осталось), почему я могу создать последовательность только integer-значений. Почему не могу varchar, например? Или ещё какого другого типа? Ну там, timestamp?
  • jack128_ (26.01.12 20:09) [20]
    дома дельфи нет, только предположения:
    проблема может быть в том, что IBX не считает insert за выборку данных, поэтому принудительно Eof выставляет в false для такого запроса. С другой стороны сервер таки отдает данные, поэтому FieldByName таки правильно возвращает данные
  • Ega23 © (26.01.12 20:45) [21]

    > проблема может быть в том, что IBX не считает insert за
    > выборку данных, поэтому принудительно Eof выставляет в false
    > для такого запроса. С другой стороны сервер таки отдает
    > данные, поэтому FieldByName таки правильно возвращает данные


    Ну я тоже так думаю. Совсем забыл, что в IB надо селект из ХП делать, это и смутило.
  • Johnmen © (26.01.12 22:09) [22]

    > Ega23 ©   (24.01.12 16:17)
    >
    > Так вот. Не работает. Но, как только убираем строчку if
    > not Eof - получаем сообщение с правильным id.
    >

    Дело в том, что НД в результате выполнения запроса нет. Значит Eof=True, Bof=True. И First не только не поможет, но и неприменим.
  • sniknik © (26.01.12 23:15) [23]
    > но и неприменим.
    FieldByName
    ?
  • Германн © (27.01.12 02:43) [24]

    > Johnmen ©   (26.01.12 22:09) [22]
    >
    >
    > > Ega23 ©   (24.01.12 16:17)
    > >
    > > Так вот. Не работает. Но, как только убираем строчку if
    > > not Eof - получаем сообщение с правильным id.
    > >
    >
    > Дело в том, что НД в результате выполнения запроса нет.

    "христом-богом" клянусь, что у меня была та же самая проблема с TIBSQL при запросе типа "select".
  • sniknik © (27.01.12 07:58) [25]
    ИМХО, он просто не инициализирует возвращаемый рекордсет, в датасете позиция не устанавливается на запись, и "смотрит" за... FieldByName работает как положено, оно при "выходе" указателя за "смотрит" в последнюю запись (иначе бы не работали после циклов с while not eof do, а они работают...)

    не знаю просто про TIBxxxx, но в ADO рекордсет возвращается всегда (кроме случая когда отключен опцией)... не как набор данных, но как информационная структура, с ошибками, сообщениями, out параметрами. т.е. как бы обьект содержащий и рекордсет в том числе.
  • Johnmen © (27.01.12 14:07) [26]

    > sniknik ©   (26.01.12 23:15) [23]
    > > но и неприменим.
    > FieldByName
    > ?

    FieldByName применим.
  • Johnmen © (27.01.12 14:09) [27]

    > Германн ©   (27.01.12 02:43) [24]
    > "христом-богом" клянусь, что у меня была та же самая проблема
    > с TIBSQL при запросе типа "select".

    Так дело не в select,  а в пустом НД.
  • Виталий Панасенко (27.01.12 15:19) [28]

    > Ega23 ©   (26.01.12 13:07) [14]

    А по этому поводу (я о причинах перехода): разработчики FIB+ утверждают, что будут поддерживать API как IB, так и FB... + у них реализована эмуляция логических поле (как и в примере, с созданием домена), GUID ... и многое другое.. например, 2 транзакции: одна длинная на чтение, короткая - на запись, локальная сортировка по нескольким полям, режим ограниченного чтения буфера данных(что очень приятно на больших НД), кэш БЛОБ полей на локальный диск(если меняется хэндл блоба, перечитывается, иначе БЛОБ читается с локального диска), возможность подключить функцию сжатия/распаковки для БЛОБ-полей (в итоге уменьшается трафик по сети. В отличии от фильтров самого сервера, данные пакуются и передаются на сервер уже в меньшем объеме. И наоборот, распаковываются уже на клиенте). Для мастер-детали возможно автоматического открытия мастера, задержка в открытии детали(если бежишь по приличному НД, не открывается каждый раз деталь, что экономит время).. И т.д.
  • sniknik © (27.01.12 20:09) [29]
    > Так дело не в select,  а в пустом НД.
    в данном случае, одна запись в наборе есть, иначе бы вместо
    >  ShowMessage(FieldByName('id').AsString);
    >  ... получаем сообщение с правильным id.
    получили пустую строку.
  • Johnmen © (27.01.12 21:10) [30]

    > sniknik ©   (27.01.12 20:09) [29]
    >
    > > Так дело не в select,  а в пустом НД.
    > в данном случае, одна запись в наборе есть, иначе бы вместо
    > >  ShowMessage(FieldByName('id').AsString);
    > >  ... получаем сообщение с правильным id.
    > получили пустую строку.

    В оригинале:
         if not Eof
           ShowMessage(FieldByName('id').AsString);


    (здесь пропущен then)
    Но, как только убираем строчку if not Eof - получаем сообщение с правильным id.
  • sniknik © (27.01.12 21:54) [31]
    понятно, ты считаешь, ошибка не опечатка, и Ega23 конечно ни в жизнь не разберется с сообщением о неверном синтаксисе... (сарказм)
    но не надо игнорировать суть моего сообщения. вот убрали, ошибки нет, и значение ВОЗВРАЩАЕТСЯ, правильное, что без заполненного хотя бы одной записью набора невозможно. (вот если бы там вместо FieldByName стоял ParamByName другое дело)
  • Johnmen © (27.01.12 23:02) [32]
    Дело в том, что возвращаемые при выполнении запроса (любого) данные (все) помещаются в специально выделенную в памяти область (дескриптор вывода XSQLDA). Для рассматриваемого случая FieldByName берет данные из этой области. При этом НД как такового нет, но есть возвращенные по выполнении запроса данные, лежащие там же.
    Если говорить абстрактно-образно, то FieldByName эквивалентно ParamByName в данном случае.
    Если есть сомнения в моих словах, то исходники доступны всем...
  • sniknik © (28.01.12 10:10) [33]
    > При этом НД как такового нет, но есть возвращенные по выполнении запроса данные, лежащие там же.
    если что-то выглядит как ..., пахнет как ..., ведет себя как ..., то это и есть ... оно.  неважно из какого места вышло.

    рекорсет который не рекордет, но все функции кроме одной к нему применимы... надо же. выглядит как глюк, в логике, и код смотреть не надо. ADO ведет себя более "честно" если рекордсета нет, по опции "неполучения", то любая операция с ним вернет ошибку.... и ни каких неоднозначностей.
  • turbouser © (28.01.12 11:50) [34]

    > Ega23 ©

    все-таки FIB лучше купить. стоит копейки, а проблем очень многих можно избежать.
  • sniknik © (28.01.12 15:04) [35]
    > а проблем очень многих можно избежать.
    каких проблем? не вижу тут проблем. ну и впечатление по ветке, что Ega23 солидарен.
  • turbouser © (28.01.12 15:15) [36]
    IB и FB очень отличаются. Это во первых. Во вторых FIB создают люди весьма знающие. В отличие от индусов (по крайней мере весьма похожие на них личности), которые пилят IBX
  • turbouser © (28.01.12 15:18) [37]
    Есть еще UIB компоненты, но они в основном для серверов.
  • Ega23 © (29.01.12 13:56) [38]

    > IB и FB очень отличаются. Это во первых. Во вторых FIB создают
    > люди весьма знающие. В отличие от индусов (по крайней мере
    > весьма похожие на них личности), которые пилят IBX


    Ещё раз. Назови мне хотя бы одну вескую причину перехода с IBХ на FIB+.
    Типа: в FIB+ есть вот это вот, чего в IBX нет. Или оно работает неправильно и через опу.
  • asail © (31.01.12 02:51) [39]
    А чего говорит IsEmpty?
  • Дмитрий Белькевич (23.05.12 00:57) [40]
    >Дело в том, что НД в результате выполнения запроса нет.

    Весь НД, кстати, не всегда нужен. Для отображения - да. Для работы зачем весь набор? Занимающий память.
    Одной, текущей, записи вполне хватает при обработке большинства select'ов, зачем гору записей держать постоянно в памяти?
 
Конференция "Базы" » Наткнулся на любопытное поведение TIBSQL [FireBird 2.1]
Есть новые Нет новых   [119628   +43][b:0][p:0.001]