:: Visual Foxpro, Foxpro for DOS
Странно работает курсорадаптер
Sandwich
Автор

Сообщений: 137
Дата регистрации: 08.02.2014
Всем здравствуйте.
битых 2 часа пытаюсь решить такую проблему:
Создал курсорадаптер, через ODBC подключенный к БД MySQL.Buffer mode override=Optimistic row buffering
Попытка в run-time изменить содержимое поля в курсоре не приводит к изменению в БД.
Пробовал и через replace+go top и через update where.
Причем в design-time (из командной строки и ручками в окне BROWSE) все работает корректно.
Добавление строк (insert) нормально работает и в run-time и в design-time.
Ratings: 0 negative/0 positive
Re: Странно работает курсорадаптер
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Вообще-то стоит использовать табличный режим буферизации и явное сохранение по tableupdate() - с проверкой сработало оно или нет - и если нет, то по какой причине через aerror()
А так - полное отсутствие кода никак не способствует помощи Можно лишь предположить что в IDE и в рантайме разные установки действуют, и какие-то из них влияют на процесс... При том что сам CAD, возможно, не полностью настроен - например не используется схема.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Странно работает курсорадаптер
Sandwich
Автор

Сообщений: 137
Дата регистрации: 08.02.2014
Igor Korolyov
А так - полное отсутствие кода никак не способствует помощи
Я мог бы привести полный текст replace или update, но сомневаюсь что это что-то прояснило бы
Igor Korolyov
При том что сам CAD, возможно, не полностью настроен - например не используется схема.
В проекте полтора десятка CAD, все построены одинаково (схема используется) и работают корректно (кроме этого)
Igor Korolyov
Вообще-то стоит использовать табличный режим буферизации и явное сохранение по tableupdate()
А вот это дало положительный результат.
В чем может быть причина? Глюк?
Ratings: 0 negative/0 positive
Re: Странно работает курсорадаптер
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Интересует не replace/update меняющий курсор, а код задающий CAD - все его свойства/настройки. Именно это определяет как именно изменённые данные из курсора управляемого CAD передадутся в таблицу на сервере.
Если явный tableupdate помог, то осталось:
- привести таки код описания CAD - имена полей можно заменить на "незначащие", главное сохранить ВСЕ настройки адаптера.
- показать какой именно tableupdate помог - его параметры.
- проверить действительно ли курсор находится в 3 режиме буферизации, или всё же каким-то кодом переведен в 5-й, и ни о каком "самостоятельном" сбросе изменений на сервер речи идти уже не может (хотя если insert проходит, то дело скорее всего не в этом).
- проверить структуру курсора, её соответствие структуре в CAD и структуре в серверной таблице. Особое внимание обратить на char/varchar поля, их размеры, наличие "хвостовых пробелов" на сервере, и, возможно ConversionFunc. Аналогично для числовых полей - особенно с дробной частью. Ошибки в этих настройках будут приводить к тому, что при попытке обновить данные фокс сгенерирует такую SQL команду, которая "не узнает" исходную строку - скажем фокс сгенерирует команду update tbl set ... where id = csr.id and name = csr.name and salary = csr.salary на сервере в varchar поле name будет "чистое", без хвостовых пробелов значение "Вася", а в поле salary числовое значение, к примеру, 12345.678 - а у тебя в фоксе поле name указано как C(20) - т.е. дописывает кучу ненужных пробелов к значению, а поле salary имеет тип N(10,2) - и "теряет" младший разряд числа. Естественно подобная update команда ничего на сервере не обновит. Тогда как указав в tableupdate второй параметр как .T. ты автоматом "выкинешь" из генерируемой команды оба условия по name и salary, оставив там лишь поиск по id - и всё волшебным образом "заработает".

P.S. Вообще крайне не советую использовать "автоматическое" сохранение данных из курсора при перемещении указателя записи - т.е. 3-й режим буферизации. Он неуправляем и практически неконтролируем. А вот в 5-м режиме, при явном tableupdate всё чётко и строго - и видно сразу прошло сохранение или нет, и можно посмотреть на причину/ошибку если оно неуспешно... Да и в общем само сохранение происходит не абы когда, а в строго определённый момент - например при нажатии кнопки сохранить, или при попытке закрытия формы редактирования.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Странно работает курсорадаптер
Sandwich
Автор

Сообщений: 137
Дата регистрации: 08.02.2014
Igor Korolyov
Igor Korolyov
Дело было не в "бобине"
Я долго не мог понять, почему обновление данных на сервере происходит ИНОГДА (в независимости от режима буферизации 3 или 5).
И наконец-то нашел причину: проблема в поле типа Date.
Если среди изменяемых полей его нет - все работает правильно.
Если это поле есть - обновление не происходит (точнее не всегда).
В БД это поле стоит NOT NULL и при добавлении новой строки оно заполняется '0000-00-00'.
И если в момент обновления в поле стоит '0000-00-00', то обновления нет, если реальная дата (например '2018-05-14') - обновление происходит.

БД моя - убрал NOT NULL - все стало работать корректно.

НО
1. Что делать в такой ситуации, если менять структуру БД нельзя?
2. В Foxe теперь при пустых датах в Gride стоят NULL - некрасиво
Ratings: 0 negative/0 positive
Re: Странно работает курсорадаптер
ssa

Сообщений: 12999
Откуда: Москва
Дата регистрации: 23.03.2005
Sandwich
В БД это поле стоит NOT NULL и при добавлении новой строки оно заполняется '0000-00-00'.
И если в момент обновления в поле стоит '0000-00-00', то обновления нет
И при этом наверняка выскакивала ошибка 1526 с руганью сервера именно по этому поводу.
Цитата:
1. Что делать в такой ситуации, если менять структуру БД нельзя?
2. В Foxe теперь при пустых датах в Gride стоят NULL - некрасиво
Научиться работать с null.

------------------
Лень - это неосознанная мудрость.
Ratings: 0 negative/0 positive
Re: Странно работает курсорадаптер
Sandwich
Автор

Сообщений: 137
Дата регистрации: 08.02.2014
ssa
Научиться работать с null.
Ну слава богу, хоть кто-то помог!
Хоть кто-то разъяснил, чему надо учиться!
Только Вы забыли добавить: Воспользуйся поиском.
Одно не понятно: как же Вы, патриций, с нами плебеями на одном форуме? Не солидно как-то.
Ratings: 0 negative/0 positive
Re: Странно работает курсорадаптер
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Sandwich
Дело было не в "бобине"

Igor Korolyov
проверить структуру курсора, её соответствие структуре в CAD и структуре в серверной таблице.

Igor Korolyov
Ошибки в этих настройках будут приводить к тому, что при попытке обновить данные фокс сгенерирует такую SQL команду, которая "не узнает" исходную строку - скажем фокс сгенерирует команду update tbl set ... where id = csr.id and name = csr.name and salary = csr.salary на сервере в varchar поле name будет "чистое", без хвостовых пробелов значение "Вася", а в поле salary числовое значение, к примеру, 12345.678 - а у тебя в фоксе поле name указано как C(20) - т.е. дописывает кучу ненужных пробелов к значению, а поле salary имеет тип N(10,2) - и "теряет" младший разряд числа. Естественно подобная update команда ничего на сервере не обновит. Тогда как указав в tableupdate второй параметр как .T. ты автоматом "выкинешь" из генерируемой команды оба условия по name и salary, оставив там лишь поиск по id - и всё волшебным образом "заработает".

and date = csr.date
на сервере в поле будет null, у тебя в фоксе "пустая дата", которая не есть null.

Так что прежде чем давать свои категоричные заключения, следует подумать над написанным.
Ну и хамить не надо...


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Странно работает курсорадаптер
Sandwich
Автор

Сообщений: 137
Дата регистрации: 08.02.2014
Igor Korolyov
следует подумать над написанным
Я не только подумал, но и проверил различные варианты настроек CAD, типа полей в серверной таблице и способов обновления.
Igor Korolyov
Тогда как указав в tableupdate второй параметр как .T. ты автоматом "выкинешь" из генерируемой команды оба условия по name и salary, оставив там лишь поиск по id - и всё волшебным образом "заработает".
Конечно заработало, но таким способом без предупреждения "убьются" все данные, которые мог внести другой пользователь.
Следующим логическим шагом д.б. второй параметр .F. и проверка по AERROR() и дальнейшие действия по результатам анализа полученной ошибки.

Поэтому я повторю свой вопрос ещё раз: если в БД в поле date стоит NOT NULL, то tableupdate(1,.f.) при ConflictCheckType=3 генерирует ошибку 1585. Как исключить эту ошибку не прибегая к корректировке структуры БД и не "убивая" возможные чужие изменения путем tableupdate(1,.t.)?
Igor Korolyov
Ну и хамить не надо...
Если уж мой ответ (пусть и резкий) на такую пустую реплику SSA звучит хамски, то:
Уважаемый SSA, примите извинения.
Ratings: 0 negative/0 positive
Re: Странно работает курсорадаптер
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Если во внешней СУБД некоторое поле имеет значение по умолчанию, или любой иной вариант "автоматического заполнения" (например через триггер), то в фоксе следует использовать механизм обновления (рефреша) записей после вставки. Чтобы затянуть обратно те значения полей, которые были заданы на сервере (и чтобы данные в курсоре не отличались от данных на сервере после сохранения записи). К слову, если есть на сервере поля изменяемые при модификации записи (типа timestamp или "дата последнего изменения записи" заполняемая в триггере) то механизм рефреша следует применять не только к Insert, но и к Update командам. Это всё настраивается через группу свойств InsertCmdRefreshCmd, InsertCmdRefreshFieldList, InsertCmdRefreshKeyFieldList ну и аналогичная группа UpdateCmd* для рефреша после "модификации записи".
В зависимости от логики работы с курсором, может оказаться более простым/правильным не "рефреш" на уровне одиночных записей, а полный перезапрос (Requery) курсора после сохранения изменений из него на сервер (т.е. после tableupdate).
Другой вариант, или, скорее, фикс некоторых подобных моментов - это всегда ЯВНО задавать в фоксовом курсоре значения для полей имеющих default value на сервере. Тогда фокс при insert отправит на сервер "своё" значение, и автоматика default value не будет работать. Но это не поможет, если "автомат присвоения" на сервере всё одно перезапишет пришедшее с клиента значение поля на своё - чаще всего это будет происходить при присвоении значений в триггере (не в курсе за MySQL, а в других СУБД это вполне обычная практика - правда аккуратно написанный триггер может и не "перебивать" значение, если оно явно было послано с клиента - ну и если оно не противоречит бизнес-логике). Ну и это не поможет для уже имеющихся в БД записей с "неправильными" значениями полей.

Теперь конкретно к "пустым датам" - в фоксе недопустимо значение даты 0000-00-00 - его нельзя никак получить (всё что "раньше" 0000-03-00 хоть и "рисуется" как пустая дата, тем не менее таковой не является, что легко увидеть применив EMPTY() или сравнение с {}
Во что "превращается" фоксовая пустая дата при посылке на внешний сервер - это уже нюансы реализации конкретных ODBC драйверов и конкретных серверов. В большинстве СУБД нет в принципе "пустой даты", в MSSQL, насколько я помню, фоксовая пустая дата преобразуется в совсем уж "непустую" 1900-01-01...
В общем не следует использовать фоксовую пустую дату при работе с внешними СУБД.
Если логика задачи позволяет, следует использовать NULL - настройка его отображения в фоксе достаточно гибкая - от "общего" SET NULLDISPLAY до "конкретных" свойств NullDisplay текстобоксов, спиннеров и ряда других элементов управления. Конечно же надо чётко понимать как "работает" NULL - в частности что это НЕ "пустая дата" и даже НЕ "значение", что сравнение поле=NULL или поле!=NULL являются некорректными...
Если логику задачи под "правильный" NULL нельзя перевести, то следует выбрать какую-то определённую дату и считать это конкретное значение за "пустоту". При этом следует проверить, что эта дата корректно преобразуется между фоксом и используемой СУБД, и не создаёт проблем в других использующих эту БД программах (скажем для дат ранее 1601 года многие программы и даже среды программирования ведут себя некорректно - даже фокс "спотыкается" при SET DATE LONG/SHORT).
Естетсвенно уже имеющиеся в БД даты "неправильного" вида следует исправить и привести к выбранному варианту. Т.е. дата 0000-00-00 для фокса - явно "не прокатит".


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Странно работает курсорадаптер
Sandwich
Автор

Сообщений: 137
Дата регистрации: 08.02.2014
Спасибо
Igor Korolyov
В общем не следует использовать фоксовую пустую дату при работе с внешними СУБД.
Наверное все-таки не так:
При работе из FoxPro с внешними СУБД, в которых поля типа Date установлены NOT NULL, следует иметь в виду, что возможна некорректная работа
Ratings: 0 negative/0 positive
Re: Странно работает курсорадаптер
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Корректная работа с "пустой датой", даже если такое понятие и есть во внешней СУБД - весьма маловероятна. Соответственно фоксовая "пустая дата" и не должна использоваться. NULL/NOT NULL констрейн на поле (что во внешней БД, что в фоксовом курсоре) к этому прямого отношения не имеет - вероятно он лишь повляил на то что сервер какой-то свой аналог "пустой даты" стал в поле записывать. Я не знаком со спецификой MySQL, а в других СУБД попытка НЕ указать значение в момент вставки при наличии констрейна NOT NULL и отсутствии явного default value в поле (либо задания значения для этого поля в триггере) приведёт к ошибке и запись просто не будет создана вообще - никаких 0000-00-00 или иных "пустых дат" ни MSSQL, ни Oracle не подсунут.

Некорректная работа может быть и с непустыми датами - скажем с датами меньше 1601 года для некоторых СУБД.
И, конечно, с полями datetime если их забирать в фоксовое поле типа date - обрезка "времени" тоже приведёт к подобным ошибкам для любой записи где время отлично от полуночи. По сути это false positive фоксовой ошибки "Update conflict" - т.е. фокс считает что данные во внешней БД изменились (т.к. они реально отличаются от тех данных которые у него в курсоре находятся). Хотя на самом деле проблема возникла в момент извлечения, когда данные были преобразованы и в процессе этого преобразования была "потеряна точность", или прилипли "хвостовые пробелы", или вот такие вот нюансы "пустоты непустых дат" возникли.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Странно работает курсорадаптер
Sandwich
Автор

Сообщений: 137
Дата регистрации: 08.02.2014
Igor Korolyov
Igor Korolyov
Спасибо за развернутые ответы.
Буду иметь эту инфу в виду при дальнейшей работе
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 34 (Гостей: 34)

© 2000-2024 Fox Club 
Яндекс.Метрика