15.05.2008, 11:25 | #1 |
Участник
|
поля, содержащие RecId
Dear All!
В Аксапте 3.0 ищу поля-ссылки на RecId (кроме самих RecId). Действую так: 1. Нахожу поля с типами-наследниками recId, кроме собственно полей RecId (через dictType.extend()). 2. Нахожу поля, имеющие связи (указанные как в таблицах, так и в EDT) с полями типов-наследников recId, кроме собственно полей RecId (через dictRelation.loadNameRelation() и dictRelation.loadFieldRelation()). 3. Устраняю дубликаты пар таблица-поле. Но вот здесь есть такая информация: Цитата:
Сообщение от Yaroslav Batozskiy
при дефрагментировании RecId я обнаружил, что есть поля со ссылками по Recid, тип которых не наследуется от RecId (в результате чего при экспорте-импорте эти ссылки пересчитаны не будут, т.е. данные в таблице будут повреждены). Пример—поле RTSLSessionTransId в таблице LedgerTrans
P. S. Ясно, что при неграмотной модификации ссылки на RecId могут быть вообще в неких integer-полях любого типа, и узнать об этом можно, лишь прошерстив код на предмет присвоения RecId... Но и не хотелось бы лазить по коду, дабы выяснить то же для штатного функционала. |
|
15.05.2008, 13:34 | #2 |
Участник
|
Цитата:
Сообщение от somebody
В Аксапте 3.0 ищу поля-ссылки на RecId (кроме самих RecId). Действую так:
1. Нахожу поля с типами-наследниками recId, кроме собственно полей RecId (через dictType.extend()). 2. Нахожу поля, имеющие связи (указанные как в таблицах, так и в EDT) с полями типов-наследников recId, кроме собственно полей RecId (через dictRelation.loadNameRelation() и dictRelation.loadFieldRelation()). 3. Устраняю дубликаты пар таблица-поле. найти все поля, тип которых унаследован от refRecId. Это специальный тип, который согласно рекомендациям, должен содержать ссылки на RecId. Но некоторые разработчики рекомендации не используют. Поэтому окончательный поиск надо делать при помощи вашего подхода. Но сначала просто выбрать все, что унаследовано от refRecId |
|
15.05.2008, 13:39 | #3 |
Участник
|
Цитата:
Сообщение от mazzy
сначала просто выбрать все, что унаследовано от refRecId
Вопрос был - есть ли где-то список "неправильных" полей штатного функционала? Или, может, кто-то знает ещё такие поля? |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
15.05.2008, 13:51 | #4 |
Участник
|
Цитата:
Были проблемы подобного рода в сопоставлении платежей (по-моему таблица SpecTrans). Куча в зарплате, в налоговом учете в русском генераторе российской отчетности. Я бросил составлять подобный список когда понял, что в каждом сервис-паке он разный. Отличается немного, но отличается. Кроме того, мы зачастую работаем у клиентов, у которых внедряли другие партнеры.... В этих случаях подобный список вообще непредсказуем. Поэтому вместо общего списка начал делать конкретные списки для каждого конкретного случая. |
|
|
За это сообщение автора поблагодарили: somebody (1). |
15.05.2008, 13:52 | #5 |
Участник
|
если составите, опубликуете и будете поддерживать подобный список - мегареспект вам и мегауважуха.
|
|
15.05.2008, 14:46 | #6 |
Member
|
Цитата:
Сообщение от somebody
...
Вопрос был - есть ли где-то список "неправильных" полей штатного функционала? Или, может, кто-то знает ещё такие поля?...
__________________
С уважением, glibs® |
|
15.05.2008, 18:00 | #7 |
Участник
|
Цитата:
Сообщение от glibs
Насколько я помню, ответ на него был дан в той же теме, из которой приведена цитата в первом сообщении данной темы. Почитайте ее всю внимательно.
Есть там ссылка на боковую ветку, там несколько примеров проблемных таблиц, дискуссия по LedgerTrans.RTSLSessionTransId и описание работы некоего коммерческого скрипта. Да, мысль была, проверять все integer-поля. Мысль не понравилась... Проще код перелопатить... |
|
16.05.2008, 08:52 | #8 |
Member
|
Цитата:
Сообщение от somebody
...
там несколько примеров проблемных таблиц ... В 3.0 в стандартной функциональности в 3.0 была одна таблица smmTransLog. Цитата:
Сообщение от somebody
...
Проще код перелопатить ...
__________________
С уважением, glibs® |
|
16.05.2008, 10:12 | #9 |
Участник
|
2 glibs
1) Т. е. такая таблица с полем (не наследующимся от recId, но хранящим ссылку на RecId) только одна в стандартной функциональности 3.0, и это smmTransLog? 2) Имеется в виду поле smmTransLog.RefRecId? Оно имеет тип smmLogRecId, к-рый не наследуется от recId/RefRecId. Если это поле RefRecId, то в отношении DocuRef таблицы прописана его связь с DocuRef.RecId. Т. е. хотя поле не наследует recId, оно отлавливается по связи методом, к-рый обрисован в моём 1-м сообщении. 3) Подскажите пожалуйста, откуда вообще такая информация? Цитата:
Сообщение от glibs
Перелопатьте
|
|
16.05.2008, 14:03 | #10 |
Member
|
Цитата:
Сообщение от somebody
...
Т. е. такая таблица с полем (не наследующимся от recId, но хранящим ссылку на RecId) только одна в стандартной функциональности 3.0, и это smmTransLog? ... Цитата:
Сообщение от somebody
...
Имеется в виду поле smmTransLog.RefRecId? ... Цитата:
Сообщение от somebody
...
оно отлавливается по связи методом, к-рый обрисован в моём 1-м сообщении. ... Цитата:
Сообщение от somebody
...
3) Подскажите пожалуйста, откуда вообще такая информация? ... Про smmTransLog в свое время первым на моей памяти опубликовался Maxim Gorbunov. tutorial_AuctionBids нашел я. Цитата:
Сообщение от somebody
...
Имел в виду, что легче просмотреть код, чем написать более-менее адекватный скрипт по проверке integer-полей, не содержится ли в них ссылка на RecId. Адекватный в смысле результата, а полной точности в результатах скрипта всё равно не будет ...
__________________
С уважением, glibs® |
|
16.05.2008, 14:08 | #11 |
Member
|
А, вот еще условно проблемная таблица.
SysSearchPath Почитайте все таки внимательно Как выполнять дефрагментирование RecID если действительно серьезно интересуетесь проблемой. Там много полезной информации.
__________________
С уважением, glibs® |
|
16.05.2008, 14:15 | #12 |
Member
|
Вот джоб, о котором я веду речь. Писался под 3.0. Но на 4.0, вроде, запускается.
static void findBadRefRecId(Args _args) { UtilElements utilElements; DictTable dictTable; DictField dictField; DictType dictType; TableName prevTable; Counter i, result, fieldsFound, tablesFound; Boolean skipField(extendedTypeId _typeId) { DictType localDictType = new DictType(_typeId); ; if (!localDictType) { return false; } switch (localDictType.id()) { case typeId2ExtendedTypeId(typeid(recId)) : case typeId2ExtendedTypeId(typeid(tableId)) : case typeId2ExtendedTypeId(typeid(ParametersKey)) : case typeId2ExtendedTypeId(typeid(classId)) : case typeId2ExtendedTypeId(typeid(FieldNum)) : case typeId2ExtendedTypeId(typeid(fieldId)) : case typeId2ExtendedTypeId(typeid(FontSize)) : case typeId2ExtendedTypeId(typeid(SessionId)) : case typeId2ExtendedTypeId(typeid(timeOfDay)) : case typeId2ExtendedTypeId(typeid(Days)) : case typeId2ExtendedTypeId(typeid(WeekDay)) : case typeId2ExtendedTypeId(typeid(InventDimFixed)) : case typeId2ExtendedTypeId(typeid(PrintCopies)) : case typeId2ExtendedTypeId(typeid(TaxReportField)) : case typeId2ExtendedTypeId(typeid(JmgSeconds)) : case typeId2ExtendedTypeId(typeid(Minutes)) : case typeId2ExtendedTypeId(typeid(Seconds)) : case typeId2ExtendedTypeId(typeid(Column)) : case typeId2ExtendedTypeId(typeid(Columns)) : case typeId2ExtendedTypeId(typeid(Yr)) : case typeId2ExtendedTypeId(typeid(Months)) : case typeId2ExtendedTypeId(typeid(NumberSequenceRange)) : return true; default : } if (localDictType.extend()) { return skipField(localDictType.extend()); } return false; } str typesChain(extendedTypeId _typeId) { DictType chainDictType = new DictType(_typeId); str ret; ; if (chainDictType) { ret = ret + strfmt(" --> %1", chainDictType.name()); } if (chainDictType.extend()) { ret = ret + strfmt("%1", typesChain(chainDictType.extend())); } return ret; } ; while select utilElements order by name where utilElements.recordType == UtilElementType::Table { if (prevTable != utilElements.name) { dictTable = new DictTable(tablename2id(utilElements.name)); if (!dictTable.isMap() && !dictTable.isView() && !dictTable.isTmp()) { info (strfmt("%1", dictTable.name())); tablesFound++; result = 0; for (i = 1; i <= dictTable.fieldCnt(); i++) { dictField = new DictField(dictTable.id(), dictTable.fieldCnt2Id(i)); if (dictField.baseType() == Types::Integer && !dictField.isSystem() && !skipField(dictField.typeId())) { dictType = new DictType(dictField.typeId()); info (strfmt(" %1 -- %2", dictField.name(), dictType ? typesChain(dictField.typeId()) : int2str(dictField.typeId()))); // if (dictType) // { // info (strfmt(" %1 -- %2", dictType.label(), dictType.help())); // } fieldsFound++; result++; } } if (!result) { infolog.cut(infolog.line()); tablesFound--; } } } prevTable = utilElements.name; } info (strfmt("Total number of tables found: %1", tablesFound)); info (strfmt("Total number of fields found: %1", fieldsFound)); }
__________________
С уважением, glibs® |
|
16.05.2008, 14:18 | #13 |
Administrator
|
Если у вас есть 4-ка (имеется в виду все файлы с установочного диска), то там в подкаталоге DatabaseUpgrade есть проект UpgradeColumnList (для 3-шки), основное назначение которого - подготовить список всех полей, которые нужно обновить при переходе с 3-шки на 4-ку. Поскольку принципиально изменился тип только у полей с RecId (стал 64-битный), то можно считать данный проект - как создание списка всех полей всех таблиц в которых хранится RecId. Плюс в том, что данный проект - от Микрософта - т.е. его (проект) они тестировали (по крайней мере на SQL Server 2005).
Данный проект запускается на 3-шке перед переливкой данных на 4-ку
__________________
Возможно сделать все. Вопрос времени |
|
|
За это сообщение автора поблагодарили: somebody (1). |
16.05.2008, 14:27 | #14 |
Member
|
Я так подозреваю, что тот проект, как и дефрагментация RecId в 3.0, работает по RefRecId. Вопрос как раз в том, как убедиться в том, что все поля, в которых реально хранится RecId, унаследованы от нужного типа.
Со стандартными таблицами, вроде, все ОК. А вот если есть модификации, то такой проверкой придется заниматься. Микрософт не поможет тут.
__________________
С уважением, glibs® |
|
|
За это сообщение автора поблагодарили: somebody (1). |
16.05.2008, 16:14 | #15 |
Administrator
|
Спорить не буду, Микрософт не поможет. Однако - одно дело дописать, а другое дело написать один и тот же код. Заодно и узнать - может какие-то поля "в лоб" прописаны.
Т.е. проект стоит считать шаблоном/примером, но никак не руководством к действию (только после проверки и "подкрутки")
__________________
Возможно сделать все. Вопрос времени |
|
16.05.2008, 17:50 | #16 |
Участник
|
2 sukhanchik
Как было сказано, собственно поля, созданные согласно рекомендациям, мной уже найдены алгоритмом, описанным в первом сообщении. Поэтому UpgradeColumnList ничего нового не даст. Вопрос в том, чтобы найти поля, созданные вопреки рекомендациям: с типами, не унаследованными от RefRecId (или уж хотя бы напрямую от recId), и в то же время содержащие значения RecId. 2 glibs Спасибо за скрипт, это очень хорошая идея, перебрать все подозрительные integer-поля таким образом, пропуская некоторые типы. Я добавил ещё некоторые типы, к-рые стоит игнорировать (IMHO): TimeUnits PositiveDays PositiveMonths createdTime modifiedTime Periods IntvMth IntvQr IntvWk enumId CCColor OLE_Color MaximumLength MinimumLength CACPriority Priority BatchPeriodic HWND LabelIdNum extendedTypeId ColumnWidth NegativeAdjustment NoOfDecimals OprNum AssetInterval AssetLifeTime AssetLifeTimeRest indexId CovStatus SysCodeProfilerAOS* SysCodeProfilerSQL* OLAPCube* OLAPDatabase* OLAPView*. В итоге получается довольно обозримый список полей, просмотрев к-рый, получим большую уверенность, что мы ничего не упустили. Скрипт с добавленными типами и с выводом чуть понагляднее, к-рый теперь запускаю: X++: // Находим integer-поля, в которых МОГУТ находиться значения RecId, с типом, не унаследованным от recId static void findProbablyBadRefRecId(Args _args) { UtilElements utilElements; DictTable dictTable; DictField dictField; DictType dictType; TableName prevTable; Counter i, result, fieldsFound, tablesFound; Boolean skipField(extendedTypeId _typeId) { DictType localDictType = new DictType(_typeId); ; if (! localDictType) { return false; } switch (localDictType.id()) { case typeId2ExtendedTypeId(typeid(recId)) : case typeId2ExtendedTypeId(typeid(tableId)) : case typeId2ExtendedTypeId(typeid(ParametersKey)) : case typeId2ExtendedTypeId(typeid(classId)) : case typeId2ExtendedTypeId(typeid(FieldNum)) : case typeId2ExtendedTypeId(typeid(fieldId)) : case typeId2ExtendedTypeId(typeid(FontSize)) : case typeId2ExtendedTypeId(typeid(SessionId)) : case typeId2ExtendedTypeId(typeid(timeOfDay)) : case typeId2ExtendedTypeId(typeid(Days)) : case typeId2ExtendedTypeId(typeid(WeekDay)) : case typeId2ExtendedTypeId(typeid(InventDimFixed)) : case typeId2ExtendedTypeId(typeid(PrintCopies)) : case typeId2ExtendedTypeId(typeid(TaxReportField)) : case typeId2ExtendedTypeId(typeid(JmgSeconds)) : case typeId2ExtendedTypeId(typeid(Minutes)) : case typeId2ExtendedTypeId(typeid(Seconds)) : case typeId2ExtendedTypeId(typeid(Column)) : case typeId2ExtendedTypeId(typeid(Columns)) : case typeId2ExtendedTypeId(typeid(Yr)) : case typeId2ExtendedTypeId(typeid(Months)) : case typeId2ExtendedTypeId(typeid(NumberSequenceRange)) : case typeId2ExtendedTypeId(typeid(TimeUnits)) : case typeId2ExtendedTypeId(typeid(PositiveDays)) : case typeId2ExtendedTypeId(typeid(PositiveMonths)) : case typeId2ExtendedTypeId(typeid(createdTime)) : case typeId2ExtendedTypeId(typeid(modifiedTime)) : case typeId2ExtendedTypeId(typeid(Periods)) : case typeId2ExtendedTypeId(typeid(IntvMth)) : case typeId2ExtendedTypeId(typeid(IntvQr)) : case typeId2ExtendedTypeId(typeid(IntvWk)) : case typeId2ExtendedTypeId(typeid(enumId)) : case typeId2ExtendedTypeId(typeid(CCColor)) : case typeId2ExtendedTypeId(typeid(OLE_Color)) : case typeId2ExtendedTypeId(typeid(MaximumLength)) : case typeId2ExtendedTypeId(typeid(MinimumLength)) : case typeId2ExtendedTypeId(typeid(CACPriority)) : case typeId2ExtendedTypeId(typeid(Priority)) : case typeId2ExtendedTypeId(typeid(BatchPeriodic)) : case typeId2ExtendedTypeId(typeid(HWND)) : case typeId2ExtendedTypeId(typeid(LabelIdNum)) : case typeId2ExtendedTypeId(typeid(extendedTypeId)) : case typeId2ExtendedTypeId(typeid(ColumnWidth)) : case typeId2ExtendedTypeId(typeid(NegativeAdjustment)) : case typeId2ExtendedTypeId(typeid(NoOfDecimals)) : case typeId2ExtendedTypeId(typeid(OprNum)) : case typeId2ExtendedTypeId(typeid(AssetInterval)) : case typeId2ExtendedTypeId(typeid(AssetLifeTime)) : case typeId2ExtendedTypeId(typeid(AssetLifeTimeRest)) : case typeId2ExtendedTypeId(typeid(indexId)) : case typeId2ExtendedTypeId(typeid(CovStatus)) : return true; default : } if (localDictType.name() like "SysCodeProfilerAOS*" || localDictType.name() like "SysCodeProfilerSQL*" || localDictType.name() like "OLAPCube*" || localDictType.name() like "OLAPDatabase*" || localDictType.name() like "OLAPView*") { return true; } if (localDictType.extend()) { return skipField(localDictType.extend()); } return false; } str typesChain(extendedTypeId _typeId) { DictType chainDictType = new DictType(_typeId); str ret; ; if (chainDictType) { ret = ret + strfmt(" --> %1", chainDictType.name()); } if (chainDictType.extend()) { ret = ret + strfmt("%1", typesChain(chainDictType.extend())); } return ret; } ; while select utilElements order by name where utilElements.recordType == UtilElementType::Table { if (prevTable != utilElements.name) { dictTable = new DictTable(tablename2id(utilElements.name)); if (! dictTable.isMap() && ! dictTable.isView() && ! dictTable.isTmp()) { info (strfmt("%1", dictTable.name())); tablesFound++; result = 0; for (i = 1; i <= dictTable.fieldCnt(); i++) { dictField = new DictField(dictTable.id(), dictTable.fieldCnt2Id(i)); if (dictField.baseType() == Types::Integer && ! dictField.isSystem() && ! skipField(dictField.typeId())) { dictType = new DictType(dictField.typeId()); info (strfmt(" %1 : %2", dictField.name(), dictType ? typesChain(dictField.typeId()) : int2str(dictField.typeId()))); fieldsFound++; result++; } } if (! result) { infolog.cut(infolog.line()); tablesFound--; } } } prevTable = utilElements.name; } info (strfmt("Total number of tables found: %1", tablesFound)); info (strfmt("Total number of fields found: %1", fieldsFound)); } |
|