|
28.04.2008, 13:49 | #1 |
Участник
|
Обновление данных при переходе на Ax3 SP5 - ошибка. Караул !
Коллеги, выношу на суд общественности.
Либо я глючу, либо в процедуре обновления базы для СП5 содержится ошибка. В 5-м сервис-паке поменяли значения енумов - под это дело процедура обновления перебивает значения во всех таблицах. SQL запрос для обновления генерится тут : X++: \Classes\ChangeEnumValueInTable_W\sqlQuery X++: protected str sqlQuery(DictTable _dictTable, FieldID _fieldID, int _oldValue, int _newValue) { str szSql; str dataAreaId, dataAreaIdName; ; dataAreaIdName = _dictTable.fieldName(fieldnum(Common, DataAreaId), DbBackend::SQL); szSql = strFmt("update %1 set %2 = %3 where %2 = %4", _dictTable.name(DbBackend::Sql), _dictTable.fieldname(_fieldID, DbBackend::Sql), _newValue, _oldValue); if (_dictTable.dataPrCompany()) { dataAreaId = '\'' + curext() + '\''; if (SqlSystem::databaseBackendId() == DatabaseId::Oracle) { dataAreaId = strFmt(new SqlSystem().monocaseFmt(), dataAreaId); } szSql += " and " + dataAreaIdName + ' = ' + dataAreaId; } return szSql; } 1. Строка 19 X++: dataAreaId = '\'' + curext() + '\''; Для лечения можно попробовать поставить так X++: dataAreaId = '\'' + curExt2dataareaid(_dictTable.id()) + '\''; 2. Формирование фильтра по DataAreaId для оракла Строка 23 X++: dataAreaId = strFmt(new SqlSystem().monocaseFmt(), dataAreaId); X++: szSql += " and " + dataAreaIdName + ' = ' + dataAreaId; SUBSTR(NLS_LOWER(...)) Похоже под ораклом переход вообще не тестировался. Что это влечет : 1. Некоторые записив БД, для которых значение dataAreaId отличается от возвращаемого curExt() (например не тот регистр оказался) - могут остаться необновленными. Похоже на наше счастье значения DataAreaId сгенерированные ядром при создании записей как раз совпадают по регистру с тем что возвращает curExt() так что все нормально и все записи должны попасть. Но гарантий нет. 2. Поскольку индексы в оракле строятся тоже от функций SUBSTR(NLS_LOWER(DATAAREAID)) - то при выполнении указанных запросов любой индекс будет бесполезен - получится неэффективное сканирование таблицы даже для маленькой компании. В итоге получился вот такой исправленный код X++: protected str sqlQuery(DictTable _dictTable, FieldID _fieldID, int _oldValue, int _newValue) { str szSql; str dataAreaId, dataAreaIdName; ; dataAreaIdName = _dictTable.fieldName(fieldnum(Common, DataAreaId), DbBackend::SQL); szSql = strFmt("update %1 set %2 = %3 where %2 = %4", _dictTable.name(DbBackend::Sql), _dictTable.fieldname(_fieldID, DbBackend::Sql), _newValue, _oldValue); if (_dictTable.dataPrCompany()) { // pkoz 28.04.2008 --> //dataAreaId = '\'' + curext() + '\''; dataAreaId = '\'' + curExt2dataareaid(_dictTable.id()) + '\''; // перепроверить на корректность для повторных запусков ! // pkoz 28.04.2008 <-- if (SqlSystem::databaseBackendId() == DatabaseId::Oracle) { // pkoz 28.04.2008 --> //dataAreaId = strFmt(new SqlSystem().monocaseFmt(), dataAreaId); dataAreaId = strFmt(new SqlSystem().monocaseFmt(_dictTable.id(), _fieldID), dataAreaId); // pkoz 28.04.2008 <-- } // pkoz 28.04.2008 --> if (SqlSystem::databaseBackendId() == DatabaseId::Oracle) { szSql += " and " + strFmt(new SqlSystem().monocaseFmt(_dictTable.id(), FieldNum(common, DataAreaID)), dataAreaIdName) + ' = ' + dataAreaId; } else // pkoz 28.04.2008 <-- szSql += " and " + dataAreaIdName + ' = ' + dataAreaId; } return szSql; } Ax3.0 SP5 В качестве примера для табилцы InventTrans стандартный код сгенерил вот такой запрос X++: update INVENTTRANS set TRANSTYPE = 100 where TRANSTYPE = 21 and DATAAREAID = 'dat' X++: update INVENTTRANS set TRANSTYPE = 100 where TRANSTYPE = 21 and SUBSTR(NLS_LOWER(DATAAREAID),1,3) = SUBSTR(NLS_LOWER('dat'),1,3) Последний раз редактировалось Logger; 28.04.2008 в 14:00. |
|
28.04.2008, 15:34 | #2 |
Участник
|
Создается ощущение что это ядро с какого то момента изменило свою логику работы.
Например для SQL сервера всегда выдает выражение X++: {fn LCASE(%1)} Посмотрел по перекрестным ссылкам - вызов sqlSystem.monocaseFmt() - идет во многих местах и нигде не заданы параметры. Т.е. баг должен проявиться в куче мест. Плюс кое-где некорректно обрабатываются виртуальные компании Например тут X++: \Classes\InventUpdateTTSCleanup\updateStr |
|