| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Firebird, Interbase > Помогите разобраться с генераторами |
| Автор: RSV 25.10.2005, 08:14 |
| CDatabase m_db; CRecordset m_rs; CDBVariant var; int n_Id; char sql[] = "SELECT GEN_ID(Client_gen, 0) FROM RDB$DATABASE"; m_rs.m_pDatabase = &m_db; m_rs.Open(CRecordset::forwardOnly, sql, CRecordset::readOnly); m_rs.GetFieldValue((short)0, var); n_Id = var.m_iVal; m_rs.Close(); Вопрос. Во всех статьях о генераторах описано, что таким способом (SELECT GEN_ID(Client_gen, 0) FROM RDB$DATABASE) можно узнать текущее значение генератора Client_gen. Почему в моем приложении значение var.m_iVal при любом количестве вызова GEN_ID(Client_gen, 1)постоянно равно одному и тому же значению (28728). Версия: Firebird 1.5. Способ доступа: VC++; |
| Автор: МихаилК 25.10.2005, 11:16 |
| В GEN_ID вторым параметром идет приращение. В приведенном тобой примере он равно 0, поэтому и возвращается одно и тоже число (текущее значение генератора), попробуй изменить на 1, например. Кроме того, по непроверенным данным (слышал краем глаза) в FB1.5.0 Classic не видно изменение значения генератора после вызова функции GEN_ID в другой транзакции, до подтверждения текущей. Еще раз повторюсь - информация непроверенная, но есть некоторая вероятность ее подлинности. Удачи |
| Автор: Петрович 25.10.2005, 15:39 | ||
Сильно сомневаюсь. Иначе, вообще теряется смысл существования генераторов. Их основная ценность в том, что они живут вне механизма транзакций. |
| Автор: МихаилК 25.10.2005, 16:41 | ||
Я тоже сомневался, но один программист из нашей группы разработчиков говорит, что это так. Причем я видел собственными глазами, что в другой транзакции действительно генератор не изменял своего значения до подтверждения изменяющей транзакции. Мы с ним долго поудивлялись и решили Classic не использовать. Остается правда вероятность, что он где-то напортачил с вызовами (детално я не вникал), но вероятность этого не слишком высока. Может еще тестировалось на какой-то не релизной версии FB - сейчас мы это уже не узнаем. |
| Автор: Петрович 25.10.2005, 21:30 |
| Повторюсь несколько иначе. Если высказанное тобой предположение верно, то с таким сервером не сможет корректно работать ни одна серьезная программа! Генераторы обычно используются для получения уникальных идентификаторов записей. Следовательно, при таком поведении, идентификаторы полученные в двух паралельных транзакциях совпадут. Т.е., при сохранении будем иметь гаррантированное нарушение правила уникальности ID. Лет пять, а то и более, работаю с разными версиями IB/FB, но с таким ни разу не сталкивался. Не обижайся, но думаю что это был косяк у твоего коллеги. Без публичной демонстрации примера где такой эффект воспроизводится, никогда в такое не поверю. |
| Автор: nnm 25.10.2005, 21:39 | ||||
2 МихаилК: Не вводи, пожалуйста, народ в заблуждение - генераторы работают вне контекста транзакции и не зависят от версии сервера. Честное слово |
| Автор: МихаилК 26.10.2005, 07:53 | ||
Наверное ты в чем то прав: столь серьезное предположение просто необходимо было подкреплять примером. К сожалению сейчас нет времени заняться исследованием данного вопроса, так что не предлагаю верить мне на слово. Я просто высказал предположение исходя из имеющихся у меня данных. Кроме того я прекрасно осознаю, что генераторы просто ОБЯЗАНЫ работать вне контекста транзакций, так что мне данный случай тоже представляется скорее всего глюком. P.S. Если все-таки время появится, постараюсь воспроизвести пример и выложить тут (если конечно удасться узнать и найти версию билда FB, использовавшегося в предыдущий раз). |
| Автор: RSV 26.10.2005, 08:06 | ||||
Я извиняюсь, что вклинился в вашу беседу, но на мой вопрос о генераторах я так и не получил ответ. Почему у меня не получается на клиенте определить текущее значение генератора? Где моя ошибка? |
| Автор: Guest 26.10.2005, 17:23 |
| Объясни мне, тёмному (я не знаю VC++): var.m_iVal - это int, адрес int или что-то ещё ? |
| Автор: Петрович 26.10.2005, 18:29 | ||||
К сожалению, мои знания C++ не велики. В их рамках, мне кажется что все написано правильно. Хотя, не знаю что будет если возникнет ошибка при выполнении запроса - ты я смотрю вроде никак это не обрабатываешь.
Правильность этого ты можешь проверить в любой программе типа IBExpert, IBConsole, и пр. |
| Автор: Alex 1.11.2005, 09:14 |
| http://www.ibase.ru/devinfo/generator.htm |
| Автор: syan66 4.5.2006, 11:36 |
| Значит, экспериментировал как мог... По-разному-всякому. На форме лежит 2 TIBQuery и 2 TIBTransaction. В IBQuery1: 'SELECT GEN_ID(CLIENT_GEN, 0) FROM RDB$DATABASE', IBQuery2: 'SELECT GEN_ID(CLIENT_GEN, 1) FROM RDB$DATABASE' Две транзакции, по одной на каждый TIBQuery для чистоты эксперимента. Транзакции явно не стартуют и не коммитятся, DefaultAction taRollback. Необновление значения IBQuery1.Fileds[0] при открытии/закрытии запроса 1 получилось только в случае, многократного IBQuery2.Open без Close Выводы: 1. Генераторы меняются вне контекста транзакции 2. Ошибка в вызовах GEN_ID, 1 |