Bug 3516

Summary: Обновление динамического курсора только при изменении данных
Product: SELTA@Etersoft Reporter: Станислав Коробейников <stas>
Component: ODBC-драйверAssignee: Станислав Коробейников <stas>
Status: CLOSED FIXED QA Contact:
Severity: minor    
Priority: P4 CC: boris, goga, lav, shan
Version: 1.0.5   
Target Milestone: версия 1.0.4   
Hardware: PC   
OS: All   
Whiteboard:
Заявки RT: Связано с:
Дата напоминания:
Bug Depends on: 3720    
Bug Blocks: 2965, 3166    

Description Станислав Коробейников 2009-02-18 17:52:41 MSK
В настоящее время динамические курсоры обновляются(а точнее пересоздаются) при каждом SQLFeatchScroll. 
Надо сделать что бы они переделывались только при изменении данных в таблице, на которую они ссылаются.
Comment 1 Станислав Коробейников 2009-02-18 17:58:53 MSK
Пока решил сделать так. 

При создании курсора в odbc драйвере сохранять значение pg_stat_all_tables у таблицы этого курсора (там есть количество всех изменений). 
При SQLFetchScroll смотреть значение pg_stat_all_tables и сравнивать с сохраненным. Если оно изменилось -- обновлять.

Обновлять с помошью тригеров не получится. Т.к. тригеры не видят курсоры созданные в odbc драйвере. 

Пробую достать это значение(pg_stat_all_tables) в odbc драйвере. 
Comment 2 Станислав Коробейников 2009-02-19 18:37:53 MSK
Значение в odbc драйвере достается без проблем, создав новый handle команды. Его можно открывать при открытии курсора, а закрывать, при его закрытии. 
Таблицы можно передавать просто строкой из parser'a, при парсинге и хранить в StatementHandle, что бы не путались курсоры.

Comment 3 Станислав Коробейников 2009-02-20 17:01:06 MSK
Уже почти все наладил. Таблицы при парсинге берутся, передаются в odbc драйвер. Там при создании курсоров создается свой handle команды(внутренний), запрос, создает свой динамический курсор(внутренний).
Далее при каждом обновлении курсора, обращается уже к созданному handle команды, и обновляется уже имеющийся(внутренний) курсор, смотрит, не изменилось ли его значение. 
Если изменилось, обновляется и основной курсор. 
Далее, при уничтожении handle основной команды, уничтожается и внутренний handle. 

Все это уже работает. 
Только запрос пока автоматически не делается, я проверял уже с готовым, проверяющим изменение в одной таблице.

 
Comment 4 Станислав Коробейников 2009-02-24 13:56:21 MSK
Все доделал, закоммитил. Теперь буду смотреть. 
Comment 5 Станислав Коробейников 2009-02-24 17:36:06 MSK
Наладил, проверил. С помощью теста, действительно ли он при обновлении все-таки обновит курсор. И в 1с, просто погонял, не смотрел, как он чего обновляет.  
И то, и то работает. 
Народ просил дать ему потестить. Так что надо протестить остальные обновления, и выложить в какое-нибудь укромное место. 
Comment 6 Vitaly Lipatov 2009-02-24 19:01:11 MSK
(In reply to comment #5)
> надо протестить остальные обновления, и
> выложить в какое-нибудь укромное место. 
Укромное место для экспериментов - это
pub/Etersoft/SELTA@Etersoft/unstable/Windows/
Comment 7 Станислав Коробейников 2009-02-27 17:04:11 MSK
Падает при загрузке данных, 
это из-за того, что системные таблицы по другому обрабатываются парсером, и не регистрируются.
Их можно обновлять ничего не выясняя. 
Comment 8 Станислав Коробейников 2009-03-02 17:54:48 MSK
Ошибку нашел, но никак не могу проверить. 
SELTA вылетает с сообщеним "Порядок сортировки, установленный для бд, отличается от системного". При этом selta отправляет и получает 'a' -- все нормально, при этом все это происходит даже с selta 1.0.5. с сервера. 
Comment 9 Станислав Коробейников 2009-03-03 17:55:19 MSK
Исправил ошибку. Не падает. 
Но при тестировании выяснил, что обновляются курсоры неправильно. 
Для проверки обновления я пользуюсь функциями: pg_stat_get_tuples_inserted pg_stat_get_tuples_updated pg_stat_get_tuples_deleted
Сумма, возвращаемая этими функциями меняется поздно, т.е. при обновлении курсора не меняется. Хотя если еще раз вызвать исходный запрос, сумма уже будет новой.  
появился вопрос когда обновляются эти данные.  
В тесте все обновлялось правильно. Но там данные обновляет другой connection. 
Comment 10 Станислав Коробейников 2009-03-05 11:55:16 MSK
Выяснил, что statement тут не при чем. Имеет значение время. 
Если перед обновлением курсора, проверяющего обновления в таблице, сделать Sleep(1000) значение количества изменений в таблице меняется, Sleep(200) не успевает. Надо как-то это дело подогнать, или отказаться от использования функций pg_stat_get_tuples, а использовать триггеры.  
Comment 11 Станислав Коробейников 2009-03-05 12:47:33 MSK
Выяснилось, что есть параметр времени обновления статистики PGSTAT_STAT_INTERVAL, он равен 500мс и задается в postgres в pgstat.c. Менять его не надо. 
Comment 12 Станислав Коробейников 2009-03-05 15:01:30 MSK
Не нашел, как сделать что бы все принудительно обновилось, и похоже, что так сделать нельзя. 
Есть два варианта развития событий.
1. немного postgres подковырять. Сделать переменную, устанавливать ее каждый раз перед тем, как нужно обновлять статистику в true. В postgres'е в функции, которая сравнивает время добавить проверку на эту переменную и установку ее в false.

Если несколько человек будут разом бегать курсором по записям, обновлять статистику придется очень часто. 

2. Не использовать функции, и заменить их на триггеры. 

Придется сделать точно такую же таблицу, как и postgres'овский запрос pg_stat_all_tables. Набивать его такими же данными, некоторое дублирование.

Второй вариант, наверное получше будет. 
Comment 13 Станислав Коробейников 2009-03-06 18:19:29 MSK
Сделал с помощью триггеров. Все обновляется об обновлении поступает сразу же.
Еще не тестировал нормально.
Comment 14 Станислав Коробейников 2009-03-10 17:57:59 MSK
Падало при проведении документов (но проводило). Перепроведение все нормально проводилось.
Сделал что бы не падало. 
Comment 15 Станислав Коробейников 2009-03-11 13:30:47 MSK
Погонял, не падает, обновляется, вроде все нормально. 
Версия для тестирования:
ftp://updates.etersoft.ru/pub/Etersoft/SELTA@Etersoft/unstable/Windows/WorkCurs/selta-1.0.5.20090311.msi
Comment 16 Станислав Коробейников 2009-03-13 16:46:26 MSK
В настоящее время решается проблема увеличение времени проводок. 
Ее можно решить не делая триггеры на регистры. Но тут надо подумать об универсальности решения. 

С  статистическими функциями(pg_stat_get_tuples_*) оказалось все сложнее, чем я думал. 
Они берут данные из файла pgstat.stat. В нем хранится в структура со статистикой. А уже запихивают ее туда раз в какое-то время. Таким образом надо как-то сделать, что бы все срочно записались, а самому это подождать, если несколько человек будут этим заниматься -- это явно замедлит такую проверку. 
Не уверен в правдивости схемы на 100%, я еще посмотрю. 
Comment 17 Станислав Коробейников 2009-03-16 17:53:16 MSK
Думаю надо сделать настройки в каком-нибудь conf файле, в котором написать, на какие таблицы вешать индексы, а какие оставить в покое. 
Или нарисовать формочку и хранить это дело в реестре. 
Так же надо сделать статистику с созданием курсоров и с запросом на их пересоздание к каждой таблице. На основании этого сделать соответствующие настройки. 
Comment 18 Станислав Коробейников 2009-03-17 17:53:32 MSK
Активный пользователь предложил сделать эти настройки в самой базе (сделать отдельную табличку).
Мне кажется это хорошей идеей, 
Настройки привязаны к базе, что удобно. Триггеры может создавать функция, используя информацию из таблицы. К тому же с таким методом можно и отследить, кто этим занимается 1с или какая другая программа. 
Конечно минус может быть в том, что при загрузки/выгрузки базы эта инфа может 
не сохранится. Но с другой стороны, кто догадался настроить, тот догадается и 
сохранить. 
Comment 19 Vitaly Lipatov 2009-03-19 13:40:13 MSK
Я всё же предлагаю не забывать, что по хорошему это надо реализовать в самом сервере PG, поэтому не надо сейчас глубоко закладываться на хаки, а надо выпустить необходимые релизы, и в спокойной обстановке покопаться в PG.
Comment 20 Станислав Коробейников 2009-03-19 18:44:19 MSK
(In reply to comment #19)
> Я всё же предлагаю не забывать, что по
> хорошему это надо реализовать в самом
> сервере PG, поэтому не надо сейчас глубоко
> закладываться на хаки, а надо выпустить
> необходимые релизы, и в спокойной
> обстановке покопаться в PG.

Хорошо. В принципе почти закончил. 
Не смог узнать строку подключения 1с. Но сделал механизм. 
Есть табличка в которой лежат маски таблиц для которых надо или не надо делать триггеры. Есть функция, которая, во время первого к ней обращения заполняет табличку, а во время последующих, смотрит делает триггеры для таблиц, если они проходят по маскам. 
Можно вычислить 1с, она первым делом создает таблицу 1susers. Ну а если база уже есть, то там тем более есть эта таблица.
И надо еще посмотреть каким таблицам делать триггеры, каким нет. 



Comment 21 Станислав Коробейников 2009-03-20 16:06:39 MSK
Сделал функцию, для первоначального изготовления всех триггеров (и добавления/удаления, если изменились маски). Все изменения закинул в sql скрипты installa и update SELTA. 
Надо протестировать, работоспособность.
Но только пока в таблице с масками только написано, что не надо создавать триггеры для таблиц pg_. Надо сделать тест и на основе него сделать маски. 
Comment 22 Станислав Коробейников 2009-03-23 12:02:23 MSK
Посмотрел. Механизм работает. 
Осталось сделать нужные маски и будет работать.
Comment 23 Станислав Коробейников 2009-03-23 18:21:45 MSK
Сделал так, что бы SELTA вела логи созданных и обновлённых курсоров. Подробнее http://bugs.etersoft.ru/show_bug.cgi?id=3720
Comment 24 Vitaly Lipatov 2009-03-24 14:04:20 MSK
На всякий случай я предлагаю не забывать, что это всё временный костыль, и не надо слишком усердствовать в разработке вспомогательных средств для него.
Comment 25 Станислав Коробейников 2009-03-27 12:07:38 MSK
(In reply to comment #24)
> На всякий случай я предлагаю не забывать,
> что это всё временный костыль, и не надо
> слишком усердствовать в разработке
> вспомогательных средств для него.
> 
Да. На этом закончили. Просто добились нормальной работы.