AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 27.02.2024, 10:57   #1  
oleggy is offline
oleggy
Участник
 
272 / 36 (2) +++
Регистрация: 03.12.2019
Адрес: Россия
распарсить из SQL bin поля с содерж. контейнер AX
Привет.
Возможно ли из SQL распарить состав контейнера, если сама структура контейнера известна? Т.е. кол-во элементов в нем, типы данных каждого элемента.
Старый 27.02.2024, 11:41   #2  
SRF is offline
SRF
Участник
MCBMSS
Axapta Retail User
 
375 / 562 (19) +++++++
Регистрация: 08.08.2007
Записей в блоге: 1
гугл в помощь https://kashperuk.blogspot.com/2020/...container.html
__________________
Sergey Nefedov
Старый 28.02.2024, 20:08   #3  
dech is offline
dech
Участник
Аватар для dech
Самостоятельные клиенты AX
 
647 / 350 (13) ++++++
Регистрация: 25.06.2009
Адрес: Омск
Записей в блоге: 3
Как-то надо было распарсить контейнер из SysDatabaseLog для SSRS-отчета.
Вот кусок хранимой процедуры.
Пользуйтесь на здоровье!
PHP код:
DECLARE @Data            VARBINARY(MAX)
      , @
FieldId        INT
      
, @FieldType        TINYINT
      
, @NewValue        NVARCHAR(MAX)
      , @
OldValue        NVARCHAR(MAX)
      , @
Marker            INT
      
, @Array            INT
      
, @Id                INT
      
, @Tmp            VARBINARY(MAX)
      , @
CreateDate        DATETIME
      
, @CreateTime        INT
      
, @CreateBy        VARCHAR(5)
      , @
LogRecId        BIGINT
      
, @LogType        INT
      
, @Description    VARCHAR(60)

DECLARE 
DBLCursor CURSOR FOR
SELECT [DBL].[CreatedDate]
     , [
DBL].[CreatedTime]
     , [
DBL].[CreatedBy]
     , [
DBL].[Description]
     , [
DBL].[LogType]
     , [
DBL].[LogRecId]
     , [
DBL].[Data]
FROM SysDataBaseLog AS [DBL]
WHERE [DBL].DataAreaId N'CLT'
  
AND [DBL].Table_ 315
  
AND [DBL].CreatedDate BETWEEN @FromDate AND @ToDate

DECLARE    @DataSet TABLE (
            [
Id]            INT PRIMARY KEY
          
, [FieldId]        INT
          
, [Array]            INT
          
, [LogType]        INT
          
, [Description]    VARCHAR(60)
          , [
CreatedDate]    DATETIME
          
, [CreatedTime]    INT
          
, [CreatedBy]        VARCHAR(5)
          , [
LogRecId]        BIGINT
          
, [NewValue]        NVARCHAR(MAX)
          , [
OldValue]        NVARCHAR(MAX)
        )

SET @Id 0

OPEN DBLCursor

FETCH NEXT FROM DBLCursor
INTO 
@CreateDate, @CreateTime, @CreateBy, @Description, @LogType, @LogRecId, @Data

WHILE @@FETCH_STATUS 0
BEGIN

  
IF (@Data IS NOT NULL AND ASCII(SUBSTRING(@Data11)) = 0x07 AND ASCII(SUBSTRING(@Data21)) = 0xFD)
  
BEGIN -- Inside container
    SET 
@Marker 3

    
WHILE (@Marker <= DATALENGTH(@Data
      AND 
ASCII(SUBSTRING(@Data, @Marker1)) = 0x07
      
AND ASCII(SUBSTRING(@Data, @Marker+11)) = 0x07
      
AND ASCII(SUBSTRING(@Data, @Marker+21)) = 0xFD)
    
BEGIN
      SET 
@Marker = @Marker 3
      SET 
@Tmp SUBSTRING(@Data, @Marker5)

      --  @
Tmp[1] = 0x01 (int)
      
SET @FieldId ASCII(SUBSTRING(@Tmp21)) + 256 ASCII(SUBSTRING(@Tmp31))
      
SET @Array = ASCII(SUBSTRING(@Tmp41)) + 256 ASCII(SUBSTRING(@Tmp51))

      
SET @Marker = @Marker 5
      SET 
@FieldType ASCII(SUBSTRING(@Data, @Marker1))
      
SET @Marker = @Marker 1
      
      SET 
@NewValue dbo.PPOPeekValue(@FieldId, @FieldType, @Data, @Marker)
      
SET @Marker = @Marker + CASE @FieldType
        WHEN 0 THEN DATALENGTH
(@NewValue)+2        -- str
        WHEN 1 THEN 4                            
-- int/time
        WHEN 2 THEN 10                            
-- real
        WHEN 3 THEN 3                            
-- date
        WHEN 4 THEN 3                            
-- enum
        WHEN 8 THEN DATALENGTH
(@NewValue)+2        -- text
        WHEN 45 THEN 16                            
-- guid
        WHEN 49 THEN 8                            
-- int64
      END

      SET 
@OldValue 0
      
IF ASCII(SUBSTRING(@Data, @Marker1)) <> 0xFF
      BEGIN
        SET 
@FieldType ASCII(SUBSTRING(@Data, @Marker1))
        
SET @Marker = @Marker 1

        SET 
@OldValue dbo.PPOPeekValue(@FieldId, @FieldType, @Data, @Marker)
        
SET @Marker = @Marker + CASE @FieldType
          WHEN 0 THEN DATALENGTH
(@NewValue)+2        -- str
          WHEN 1 THEN 4                                
-- int/time
          WHEN 2 THEN 10                            
-- real
          WHEN 3 THEN 3                                
-- date
          WHEN 4 THEN 3                                
-- enum
          WHEN 8 THEN DATALENGTH
(@NewValue)+2        -- text
          WHEN 45 THEN 16                            
-- guid
          WHEN 49 THEN 8                            
-- int64
        END
      END

      
IF @FieldId <> 61450        -- Skip RecVersion fields
      BEGIN
        SET 
@Id = @Id 1
        INSERT INTO 
@DataSet ([Id], [FieldId], [Array], [CreatedDate], [CreatedTime], [CreatedBy], [Description], [LogType], [LogRecId], [NewValue], [OldValue])
          
VALUES (@Id, @FieldId, @Array, @CreateDate, @CreateTime, @CreateBy, @Description, @LogType, @LogRecId, @NewValue, @OldValue)
      
END
      
      
-- Skip last byte of container (0xFF)
      
SET @Marker = @Marker 1
    END
  END

  FETCH NEXT FROM DBLCursor
  INTO 
@CreateDate, @CreateTime, @CreateBy, @Description, @LogType, @LogRecId, @Data
END

CLOSE DBLCursor
DEALLOCATE DBLCursor 
__________________
// no comments
За это сообщение автора поблагодарили: S.Kuskov (10), Logger (10), sukhanchik (15), Ace of Database (10).
Старый 29.02.2024, 09:13   #4  
dech is offline
dech
Участник
Аватар для dech
Самостоятельные клиенты AX
 
647 / 350 (13) ++++++
Регистрация: 25.06.2009
Адрес: Омск
Записей в блоге: 3
Там еще идет функция вдовесок. В принципе не сложная, думаю.
PHP код:
CREATE FUNCTION [dbo].[PPOPeekValue](@FieldId INT, @FieldType TINYINT, @Data VARBINARY(MAX), @Position BIGINTRETURNS NVARCHAR(MAX)
AS
BEGIN
    
DECLARE @Result        NVARCHAR(MAX)
          , @
N            INT
          
, @IntValue    INT
          
, @Exp        INT
          
, @Sign        INT
          
, @FloatValue    FLOAT
          
, @Year        INT
          
, @Month        TINYINT
          
, @Day        TINYINT
          
, @BigValue    BIGINT

    
-- decode string/text values
    
IF @FieldType OR @FieldType 8
    BEGIN
        SET 
@0
        
WHILE CAST(SUBSTRING(@Data, @Position + @N2) AS SMALLINT) <> 0
            SET 
@= @2
        SET 
@Result CAST(SUBSTRING(@Data, @Position, @N) AS NVARCHAR(MAX))
    
END ELSE

    -- 
decode integer/time values
    
IF @FieldType 1
    BEGIN
        SET 
@IntValue 0
        SET 
@3
        
WHILE @>= 0
        BEGIN
            SET 
@IntValue = @IntValue 256 ASCII(SUBSTRING(@Data, @Position + @N1))
            
SET @= @1
        END
        
IF @FieldId 61441 OR @FieldId 61445
        BEGIN
            SET 
@Result CAST(dbo.PPOInt2Time(@IntValue) AS NVARCHAR(MAX));
        
END
        
ELSE
            
SET @Result CAST(@IntValue AS NVARCHAR(MAX))
    
END ELSE

      -- 
decode float values
      
IF @FieldType 2
      BEGIN
        SET 
@9
        SET 
@FloatValue 0;
        WHILE @
1
        BEGIN
            SET 
@Exp ASCII(SUBSTRING(@Data, @Position + @N1))
            
SET @FloatValue 100 * @FloatValue + (@Exp 0xF0) / 16 10 + (@Exp 0x0F)
            
SET @= @1
        END
        SET 
@Sign = CASE WHEN ASCII(SUBSTRING(@Data, @Position 11)) & 0x80 0 THEN 1 ELSE -1 END
        SET 
@Exp ASCII(SUBSTRING(@Data, @Position1))
        IF (@
Exp >= 0x80)
            
SET @Exp = @Exp 0x100
        SET 
@FloatValue = @FloatValue * @Sign POWER(CAST(10 AS FLOAT), @Exp 15)
        
SET @Result CAST(STR(@FloatValue163) AS NVARCHAR(MAX))
    
END ELSE
    
    -- 
decode date values
    
IF @FieldType 3
    BEGIN
        SET 
@Year   1900 ASCII(SUBSTRING(@Data, @Position1))
        
SET @Month  =    ASCII(SUBSTRING(@Data, @Position 11))
        
SET @Day    =    ASCII(SUBSTRING(@Data, @Position 21))
        
SET @Result CAST(@Month AS VARCHAR(2)) + '/' CAST(@Day AS VARCHAR(2)) + '/' CAST(@Year AS VARCHAR(4))
    
END ELSE

    -- 
decode enum values
    
IF @FieldType 4
    BEGIN
        SET 
@ASCII(SUBSTRING(@Data, @Position1))
        
SET @IntValue ASCII(SUBSTRING(@Data, @Position+11)) + 256 ASCII(SUBSTRING(@Data, @Position+21))
        
SELECT @Result EnumItemLabel FROM SRSAnalysisEnums AS [AE]
            
WHERE [AE].EnumId = @IntValue
              
AND [AE].EnumItemValue = @N
    END 
ELSE

    -- 
decode int64 values
    
IF @FieldType 49
    BEGIN
        SET 
@BigValue 0
        SET 
@7
        
WHILE @>= 0
        BEGIN
            SET 
@BigValue = @BigValue 256 ASCII(SUBSTRING(@Data, @Position + @N1))
            
SET @= @1
        END
        SET 
@Result CAST(@BigValue AS VARCHAR(MAX))
    
END

    
RETURN @Result
END 
__________________
// no comments
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
emeadaxsupport: AX Performance Troubleshooting Checklist Part 1A [Introduction and SQL Configuration] Blog bot DAX Blogs 0 05.09.2014 21:11
amer-ax: It was a great day! Blog bot DAX Blogs 3 29.12.2012 01:02
ax-erp: Creating SSRS-Reports in Dynamics AX 2012 – What’s no longer possible in AX-reports Blog bot DAX Blogs 0 18.07.2012 12:11
gatesasbait: Dynamics AX 2009 SSRS and SSAS Integration Tips Blog bot DAX Blogs 3 09.07.2009 13:07
Dynamics AX: SQL Sever 2008 - Performance with Dynamics AX 2009 - Resource Governor Blog bot DAX Blogs 0 23.01.2009 22:05
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 02:20.