Показать сообщение отдельно
Старый 13.04.2022, 11:03   #12  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,875 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от KiselevSA Посмотреть сообщение
Джобик отработал на AX2012R3 с одной ошибкой: для поля Partition присвоился тип Int64 вместо типа для RecId (49). Пришлось менять через SQL. Может найдется время для модификации job-а под AX2012?
Исправил.
Еще для гуидов хранится 45 вместо types::Guid

X++:
// [url=https://axforum.info/forums/showthread.php?t=39005&highlight=sqlDictionary]Программное воссоздание записей SqlDictionary для определенной таблицы[/url]
public static server void sqlDictionaryFill4Table(tableId _tableId)
{
    #macrolib.DictField
    #define.RecIdBaseType   (49)                // для полей с типом RecId/RefRecId/createdTransactionId/modifiedTransactionId используется не Types::Int64, а этот тип
    #define.TZIDsuffix      ('_TZID')           // для несистемных полей типа UtcDateTime в БД создается дополнительное поле с кодом временной зоны, в которой было записано значение

    SqlDictionary   sqlDict;
    SysdictType     dictType;
    DictTable       dictTable;
    DictField       dictField;
    ArrayIdx        arrIdx;
    Counter         numOfSqlFields;             // сколько записей для полей таблицы должно быть в SqlDictionary
    fieldName       fieldName;
    fieldId         fieldId;

    boolean processTableField(DictField _dictField, ArrayIdx _arrIdx, boolean _isTzIdField = false)
    {
        ArrayIdx    dictArrIdx;
        str         infoName;                   // это имя поля сугубо для сообщений
        FieldName   sqlName;
        boolean     ret;
        ;
        if (_isTzIdField)
        {
            if (    _dictField.baseType()   != Types::UtcDateTime
                ||  _dictField.id()         == fieldnum(Common, createdDateTime)
                ||  _dictField.id()         == fieldnum(Common, modifiedDateTime)
               )
            {
                throw error(Error::wrongUseOfFunction(funcname()));
            }
            dictArrIdx  = _dictField.arraySize() + _arrIdx;
            sqlName     = _dictField.dateTimeTimeZoneRuleFieldName(_arrIdx - 1);
            infoName    = _dictField.name() + #TZIDsuffix;
        }
        else
        {
            dictArrIdx  = _arrIdx;
            sqlName     = _dictField.name(DbBackend::Sql, _arrIdx);
            infoName    = _dictField.name();
        }
        select firstonly sqlDict
            where   sqlDict.tabId   == _dictField.tableid()
                &&  sqlDict.fieldId == _dictField.id()
                &&  sqlDict.array   == dictArrIdx
                    ;
        if (!sqlDict)
        {
            sqlDict.clear();
            sqlDict.initValue();
            sqlDict.tabId           = _dictField.tableid();
            sqlDict.fieldId         = _dictField.id();
            sqlDict.array           = dictArrIdx;
            sqlDict.name            = strupr(_dictField.name(DbBackend::Native, _arrIdx));
            sqlDict.sqlName         = sqlName;
            dictType                = new SysDictType( _dictField.typeId() );
            if (_isTzIdField)
            {
                sqlDict.fieldType   = Types::Integer;
            }
            else
            if (            _dictField.id()     == fieldnum(Common, RecId)
                ||          _dictField.id()     == fieldnum(Common, createdTransactionId)
                ||          _dictField.id()     == fieldnum(Common, modifiedTransactionId)
                ||          _dictField.id()     == fieldnum(Common, Partition)

                ||          _dictField.typeId() == extendedtypenum(RecId)
                ||          _dictField.typeId() == extendedtypenum(RefRecId)
                ||          _dictField.typeId() == extendedtypenum(createdTransactionId)
                ||          _dictField.typeId() == extendedtypenum(modifiedTransactionId)
                ||          _dictField.typeId() == extendedtypenum(Partition)

                ||  (       dictType
                    &&  (   dictType.isExtending(extendedtypenum(RecId))
                        ||  dictType.isExtending(extendedtypenum(createdTransactionId))
                        ||  dictType.isExtending(extendedtypenum(modifiedTransactionId))
                        ||  dictType.isExtending(extendedtypenum(Partition))
                        )
                    )
               )
            {
                // для RecId в поле fieldType прописывается не Types::Int64, а число 49
                sqlDict.fieldType   = #RecIdBaseType;
            }
            else
            if (            _dictField.BaseType() == Types::Guid
                ||          _dictField.BaseType() == 45 // Types_MRC::SysGuid
               )
            {
                sqlDict.fieldType   = 45;
            }
            else
            {
                sqlDict.fieldType   = _dictField.baseType();
            }
            sqlDict.strSize         = _dictField.stringLen();
            sqlDict.shadow          = bitTest( _dictField.flags(), #DBF_SHADOW );
            sqlDict.rightJustify    = bitTest( _dictField.flags(), #DBF_RIGHT );
            sqlDict.flags           = sqlDict.shadow;   // а вот ни фига не _dictField.flags();
            sqlDict.nullable        =   _dictField.baseType() == Types::Container
                                    ||  _dictField.baseType() == Types::VarString
                                        ;
            if (sqlDict.validateWrite())
            {
                sqlDict.insert();
                ret = true;
                info(strfmt(@"Создана запись для поля %1.%2%3",
                            dictTable.name(), infoName, _dictField.arraySize() > 1 ? strfmt(@"[%1]", _arrIdx) : ''
                    ));
                // для всех несистемных полей UtcDateTime создаем также связанное поле TZID
                if (   !_isTzIdField
                    &&  _dictField.baseType()   == Types::UtcDateTime
                    &&  _dictField.id()         != fieldnum(Common, createdDateTime)
                    &&  _dictField.id()         != fieldnum(Common, modifiedDateTime)
                   )
                {
                    processTableField(_dictField, _arrIdx, true);
                }
            }
            else
            {
                ret = checkFailed(strfmt(@"Запись в %1 для поля %2.%3 не была создана", tablestr(SqlDictionary), dictTable.name(), infoName));
            }
        }
        return ret;
    }
    ;
    dictTable = new DictTable( _tableId );
    if (!dictTable)
    {
        throw error(strfmt(@"Не удалось создать объект %1 для таблицы '%2' (%3)", classstr(DictTable), tableid2name( _tableId ), _tableId));
    }
    if (dictTable.isSystemTable())
    {
        throw error(strfmt(@"Таблица '%1' - системная, на это я пойтить не могу", dictTable.name()));
    }
    if (!dictTable.isSql())
    {
        throw error(strfmt(@"Таблицы '%1' вообще не должно быть в базе", dictTable.name()));
    }
    for (fieldId = dictTable.fieldNext( 0 ); fieldId; fieldId = dictTable.fieldNext( fieldId ))
    {
        dictField = dictTable.fieldObject( fieldId );
        if (dictField && dictField.isSql())
        {
            fieldName = dictField.name();
            for (arrIdx = 1; arrIdx <= dictField.arraySize(); arrIdx++)
            {
                numOfSqlFields++;
                processTableField( dictField, arrIdx );
            }
        }
    }
    select firstonly sqlDict
        where   sqlDict.tabId   == _tableId
            &&  sqlDict.fieldId == 0
                ;
    if (!sqlDict)
    {
        sqlDict.clear();
        sqlDict.initValue();
        sqlDict.tabId       = _tableId;
        sqlDict.name        = strupr(dictTable.name());
        sqlDict.sqlName     = dictTable.name(DbBackend::Sql);
        sqlDict.strSize     = numOfSqlFields;       // для "заголовка" таблицы тут указывается, сколько у нее полей в БД
        sqlDict.flags       = dictTable.isView();   // "мой дедуктивный метод..."
        sqlDict.insert();
        info(strfmt(@"Создана запись для таблицы %1", dictTable.name()));
    }
}