Problem extracting value from CONTEXT_INFO() to NVARCHAR field

  • Hi All,

    I am using the session variable context_info to log changes made to data in an audit database.

    I add a users name to the context_info variable and then extract the value via a trigger to log the users name against the audit record.

    I set the context info as follows, please note @LoginName is a parameter derived from a VARCHAR(128) field in the db:

    DECLARE @SYSUSER VARBINARY(128)

    SET @SYSUSER = CAST(CAST(@LoginName AS VARCHAR(128)) AS VARBINARY(128))

    SET CONTEXT_INFO @SYSUSER

    and extract it in my triggers as follows:

    CAST(CONTEXT_INFO() AS VARCHAR(128))

    This worked fine.

    However, I now need to support user names in languages other than English including Arabic so I changed the audit table fieldfrom VARCHAR(128) to NVARCHAR(128).

    So I'm now setting context_info as follows, please note that the field from which @LoginName is derived is now also NVARCHAR(128):

    DECLARE @SYSUSER VARBINARY(128)

    SET @SYSUSER = CAST(CAST(@LoginName AS VARCHAR(128)) AS VARBINARY(128))

    SET CONTEXT_INFO @SYSUSER

    and I extract it as follows:

    CAST(CONTEXT_INFO() AS NVARCHAR(128))

    I am now seeing what looks like chinese characters appearing in my audit tables. Here is a sample:

    呎䄠呕佈䥒奔乜呅佗䭒匠剅䥖䕃

    呎䄠呕佈䥒奔乜呅佗䭒匠剅䥖䕃

    桃楲䭳湩g

    Even stranger, this behaviour seems different from server to server, sometimes I get the correct username and sometimes the chinese characters??

    Any advice on why this worked for VARCHAR but not NVARCHAR and why the behaviour is not consistent across servers would be greatly appreciated.

    TIA,

    Chris

  • as far as I know, the data type and sizes should always be varvbinary 128 and nvarchar(64), right?

    wouldn't an implcit comversion form nvarchar to varchar mess up the data?

    or is the issue the colaltion from the end user, who might use something arabic, looks like chinse characters int eh servers default collation?

    /*

    (No column name)(No column name)

    ??????????????NT AUTHORITY\NETWORK SERVICE

    */

    DECLARE @var VARBINARY(128)

    SET @var = CAST(N'??????????????' AS VARBINARY(128))

    SET CONTEXT_INFO @var

    GO

    -- Select the context information

    DECLARE @sess VARBINARY(128), @var NVARCHAR(64)

    SET @sess = (SELECT context_info FROM master.dbo.sysprocesses

    WHERE spid = @@spid)

    SET @var = CAST(@sess AS NVARCHAR(64))

    --print @var

    SELECT CAST(context_info AS NVARCHAR(64)),

    CAST(context_info AS VARCHAR(64))

    FROM master.dbo.sysprocesses

    WHERE spid = @@spid

    Lowell


    --help us help you! If you post a question, make sure you include a CREATE TABLE... statement and INSERT INTO... statement into that table to give the volunteers here representative data. with your description of the problem, we can provide a tested, verifiable solution to your question! asking the question the right way gets you a tested answer the fastest way possible!

  • Hi Lowell,

    Thanks for the reply.

    As far as I am aware, no implicit conversation from varchar to nvarchar is taking place. The source value (@LoginName) is nvarchar(128).

    I am converting this to varbinary(128) to insert it into context_info.

    I am then extracting it back out as nvarchar(128) for insertion in the the audit db field, which is also nvarchar(128).

    This is when I see the chinese data.

    What I don't understand is that when I run the following in isolation (i.e. not inserting to the audit db table), it works and I get back the expected user name:

    DECLARE @LoginName NVARCHAR(128)

    SET @LoginName = (SELECT LoginName FROM dbo.Login WHERE LoginID = 29)

    -- Set context info for audit db triggers

    DECLARE @SYSUSER VARBINARY(128)

    SET @SYSUSER = CAST(@LoginName AS VARBINARY(128))

    SET CONTEXT_INFO @SYSUSER

    GO

    SELECT CAST(CONTEXT_INFO() AS NVARCHAR(128))

    I can't figure out where the corruption of the data is taking place.

  • ok, i can duplicate some of what you are seeing...

    try this, which is barely modified form what you posted....

    i get chinese characters from my loginnmae due to the conversion:

    what i suspect is that somewhere, ther eis a varchar column that should be nvarchar...not sure if it's occuring when assigning a value to the context info or where, but this duplicates at least a slice of the wierdness you are seeing:

    /*

    ????????e

    */

    DECLARE @LoginName VARCHAR(128)

    SET @LoginName = convert(nVARCHAR(128),suser_name())

    -- Set context info for audit db triggers

    DECLARE @SYSUSER VARBINARY(128)

    SET @SYSUSER = CAST(@LoginName AS VARBINARY(128))

    SET CONTEXT_INFO @SYSUSER

    GO

    SELECT CAST(CONTEXT_INFO() AS NVARCHAR(128))

    Lowell


    --help us help you! If you post a question, make sure you include a CREATE TABLE... statement and INSERT INTO... statement into that table to give the volunteers here representative data. with your description of the problem, we can provide a tested, verifiable solution to your question! asking the question the right way gets you a tested answer the fastest way possible!

  • chris.king (6/8/2011)


    So I'm now setting context_info as follows, please note that the field from which @LoginName is derived is now also NVARCHAR(128):

    DECLARE @SYSUSER VARBINARY(128)

    SET @SYSUSER = CAST(CAST(@LoginName AS VARCHAR(128)) AS VARBINARY(128))

    SET CONTEXT_INFO @SYSUSER

    You have shown two different pieces of code, the first one (quoted above) is converting the login name to VARCHAR(128) before VARBINARY... was this the problem?

    MM



    select geometry::STGeomFromWKB(0x0106000000020000000103000000010000000B0000001000000000000840000000000000003DD8CCCCCCCCCC0840000000000000003DD8CCCCCCCCCC08408014AE47E17AFC3F040000000000104000CDCCCCCCCCEC3F9C999999999913408014AE47E17AFC3F9C99999999991340000000000000003D0000000000001440000000000000003D000000000000144000000000000000400400000000001040000000000000F03F100000000000084000000000000000401000000000000840000000000000003D0103000000010000000B000000000000000000143D000000000000003D009E99999999B93F000000000000003D009E99999999B93F8014AE47E17AFC3F400000000000F03F00CDCCCCCCCCEC3FA06666666666FE3F8014AE47E17AFC3FA06666666666FE3F000000000000003D1800000000000040000000000000003D18000000000000400000000000000040400000000000F03F000000000000F03F000000000000143D0000000000000040000000000000143D000000000000003D, 0);

  • Forum Etiquette: How to post Reporting Services problems
  • [/url]
  • Forum Etiquette: How to post data/code on a forum to get the best help - by Jeff Moden
  • [/url]
  • How to Post Performance Problems - by Gail Shaw
  • [/url]

  • Originally, I was using VARCHAR as follows:

    DECLARE @SYSUSER VARBINARY(128)

    SET @SYSUSER = CAST(CAST(@LoginName AS VARCHAR(128)) AS VARBINARY(128))

    SET CONTEXT_INFO @SYSUSER

    This worked.

    Then came the new requirement to be able to support non-unicode characters in usernames, specifically Saudi Arabic. I then changed all the relevant fields and casts to NVARCHAR and started using:

    DECLARE @SYSUSER VARBINARY(128)

    SET @SYSUSER = CAST(CAST(@LoginName AS NVARCHAR(128)) AS VARBINARY(128))

    SET CONTEXT_INFO @SYSUSER

    This is when my problems began.

    Apologies if this wasn't made clear before.

    Thanks,

    Chris

  • chris.king (6/8/2011)


    Originally, I was using VARCHAR as follows:

    DECLARE @SYSUSER VARBINARY(128)

    SET @SYSUSER = CAST(CAST(@LoginName AS VARCHAR(128)) AS VARBINARY(128))

    SET CONTEXT_INFO @SYSUSER

    This worked.

    Then came the new requirement to be able to support non-unicode characters in usernames, specifically Saudi Arabic. I then changed all the relevant fields and casts to NVARCHAR and started using:

    DECLARE @SYSUSER VARBINARY(128)

    SET @SYSUSER = CAST(CAST(@LoginName AS NVARCHAR(128)) AS VARBINARY(128))

    SET CONTEXT_INFO @SYSUSER

    This is when my problems began.

    Apologies if this wasn't made clear before.

    Thanks,

    Chris

    just a thought...wouldn't the max NVARCHAR you could store in a VARBINARY(128) be NVARCHAR(64) ? Not that that should cause this problem....

    MM



    select geometry::STGeomFromWKB(0x0106000000020000000103000000010000000B0000001000000000000840000000000000003DD8CCCCCCCCCC0840000000000000003DD8CCCCCCCCCC08408014AE47E17AFC3F040000000000104000CDCCCCCCCCEC3F9C999999999913408014AE47E17AFC3F9C99999999991340000000000000003D0000000000001440000000000000003D000000000000144000000000000000400400000000001040000000000000F03F100000000000084000000000000000401000000000000840000000000000003D0103000000010000000B000000000000000000143D000000000000003D009E99999999B93F000000000000003D009E99999999B93F8014AE47E17AFC3F400000000000F03F00CDCCCCCCCCEC3FA06666666666FE3F8014AE47E17AFC3FA06666666666FE3F000000000000003D1800000000000040000000000000003D18000000000000400000000000000040400000000000F03F000000000000F03F000000000000143D0000000000000040000000000000143D000000000000003D, 0);

  • Forum Etiquette: How to post Reporting Services problems
  • [/url]
  • Forum Etiquette: How to post data/code on a forum to get the best help - by Jeff Moden
  • [/url]
  • How to Post Performance Problems - by Gail Shaw
  • [/url]

  • Hi Mr Magoo.

    Thanks for your replies.

    I tried changing the size of my VARBINARY to both 256 and MAX.

    Unfortunately I get the same result. It seems that when I set the context_info, it's fine but when my trigger attempts to use it, it fails. Here is my test code and trigger definition code:

    Test Code

    DECLARE @LoginName NVARCHAR(128)

    SET @LoginName = (SELECT LoginName FROM dbo.Login WHERE LoginID = 29)

    -- Set context info for audit db triggers

    DECLARE @SYSUSER VARBINARY(256)

    SET @SYSUSER = CAST(@LoginName AS VARBINARY(256))

    SET CONTEXT_INFO @SYSUSER

    GO

    SELECT CAST(CONTEXT_INFO() AS NVARCHAR(128)) -- This works

    INSERT INTO dbo.Curfew(CurfewOrderID, CurfewTypeLookupID, Description)

    VALUES (1, 55, N'Test 10')

    SELECT * FROM [EMSYS3_AUDIT].dbo.CurfewAudit -- This doesn't!!

    Trigger code fired on insert into dbo.Curfew

    SET ANSI_NULLS ON

    GO

    SET QUOTED_IDENTIFIER ON

    GO

    ALTER TRIGGER [dbo].[trg_CurfewAudit_Insert] ON [dbo].[Curfew]

    FOR INSERT

    AS

    BEGIN

    INSERT INTO [EMSYS3_AUDIT].[dbo].CurfewAudit

    (

    CurfewID,

    CurfewOrderID,

    CurfewTypeLookupID,

    Description,

    RowVersion,

    AuditLogin,

    AuditOperation,

    AuditDateTime

    )

    SELECT [inserted].CurfewID,

    [inserted].CurfewOrderID,

    [inserted].CurfewTypeLookupID,

    [inserted].Description,

    [inserted].RowVersion,

    CAST(CONTEXT_INFO() AS NVARCHAR(128)),

    0,

    GETUTCDATE()

    FROM inserted

    END

    Data inserted following Test code execution

    AuditLogin

    ????g

    Very strange!

  • CONTEXT_INFO() can only hold 128 bytes, so converting NVARCHAR(128) will lose data, but only if the login is longer than 64 characters.

    I take it the column in your audit table is NVARCHAR as well?

    MM



    select geometry::STGeomFromWKB(0x0106000000020000000103000000010000000B0000001000000000000840000000000000003DD8CCCCCCCCCC0840000000000000003DD8CCCCCCCCCC08408014AE47E17AFC3F040000000000104000CDCCCCCCCCEC3F9C999999999913408014AE47E17AFC3F9C99999999991340000000000000003D0000000000001440000000000000003D000000000000144000000000000000400400000000001040000000000000F03F100000000000084000000000000000401000000000000840000000000000003D0103000000010000000B000000000000000000143D000000000000003D009E99999999B93F000000000000003D009E99999999B93F8014AE47E17AFC3F400000000000F03F00CDCCCCCCCCEC3FA06666666666FE3F8014AE47E17AFC3FA06666666666FE3F000000000000003D1800000000000040000000000000003D18000000000000400000000000000040400000000000F03F000000000000F03F000000000000143D0000000000000040000000000000143D000000000000003D, 0);

  • Forum Etiquette: How to post Reporting Services problems
  • [/url]
  • Forum Etiquette: How to post data/code on a forum to get the best help - by Jeff Moden
  • [/url]
  • How to Post Performance Problems - by Gail Shaw
  • [/url]

  • definitely the conversion in there: here's a stark example...you'll see none of the results are the same,all due to the conversion issues:

    /*

    (No column name)(No column name)(No column name)(No column name)(No column name)(No column name)

    0x4C6F77656C6C0x4C006F00770065006C006C00LowellL???Lowell

    */

    SELECT

    convert(VARBINARY(128),'Lowell'),

    convert(VARBINARY(128),N'Lowell'),

    convert(VARCHAR(64), convert(VARBINARY(128),'Lowell')),

    convert(VARCHAR(64), convert(VARBINARY(128),N'Lowell')),

    convert(NVARCHAR(64),convert(VARBINARY(128),'Lowell')),

    convert(NVARCHAR(64),convert(VARBINARY(128),N'Lowell'))

    Lowell


    --help us help you! If you post a question, make sure you include a CREATE TABLE... statement and INSERT INTO... statement into that table to give the volunteers here representative data. with your description of the problem, we can provide a tested, verifiable solution to your question! asking the question the right way gets you a tested answer the fastest way possible!

  • Mr M: Yes, the field is an NVARCHAR. I tried reducing the size of the source data to NVARCHAR(64), it still didn't work.

  • Chris,

    Try changing your Grid results and Text Editor fonts to Arial.

    I just realised it was possible that you were trying to display arabic characters in a font that did not support them.

    I tried this on my system and voilá the arabic characters were there correctly!

    MM



    select geometry::STGeomFromWKB(0x0106000000020000000103000000010000000B0000001000000000000840000000000000003DD8CCCCCCCCCC0840000000000000003DD8CCCCCCCCCC08408014AE47E17AFC3F040000000000104000CDCCCCCCCCEC3F9C999999999913408014AE47E17AFC3F9C99999999991340000000000000003D0000000000001440000000000000003D000000000000144000000000000000400400000000001040000000000000F03F100000000000084000000000000000401000000000000840000000000000003D0103000000010000000B000000000000000000143D000000000000003D009E99999999B93F000000000000003D009E99999999B93F8014AE47E17AFC3F400000000000F03F00CDCCCCCCCCEC3FA06666666666FE3F8014AE47E17AFC3FA06666666666FE3F000000000000003D1800000000000040000000000000003D18000000000000400000000000000040400000000000F03F000000000000F03F000000000000143D0000000000000040000000000000143D000000000000003D, 0);

  • Forum Etiquette: How to post Reporting Services problems
  • [/url]
  • Forum Etiquette: How to post data/code on a forum to get the best help - by Jeff Moden
  • [/url]
  • How to Post Performance Problems - by Gail Shaw
  • [/url]

  • Just to finish this topic off, I eventually got my data posting correctly in and out of CONTEXT_INFO as an NVARCHAR. I did however find one additional problem which I thought i should add in case anyone else encounters the same issue.

    I found that the value I extracted from the CONTEXT_INFO was being padded with binary zeros up to the length I defined in my CAST or CONVERT. i.e.

    CAST(CONTEXT_INFO() AS NVARCHAR(64))

    would always give me a value padded on the right with zeros to 64 characters. This was no good as when the data was used the binary zeros would be displayed in the application requesting the data. I found the following solution to remove the padding zeros:

    REPLACE(CAST(CONTEXT_INFO() AS NVARCHAR(64)) COLLATE Latin1_General_100_BIN, 0x00, '')

    The collation could be different from server to server but this (finally) allowed me to correctly store my user's login details in an audit table via CONTEXT_INFO.

    Chris

  • Thanks Chris, that's handy to know 😀

    MM



    select geometry::STGeomFromWKB(0x0106000000020000000103000000010000000B0000001000000000000840000000000000003DD8CCCCCCCCCC0840000000000000003DD8CCCCCCCCCC08408014AE47E17AFC3F040000000000104000CDCCCCCCCCEC3F9C999999999913408014AE47E17AFC3F9C99999999991340000000000000003D0000000000001440000000000000003D000000000000144000000000000000400400000000001040000000000000F03F100000000000084000000000000000401000000000000840000000000000003D0103000000010000000B000000000000000000143D000000000000003D009E99999999B93F000000000000003D009E99999999B93F8014AE47E17AFC3F400000000000F03F00CDCCCCCCCCEC3FA06666666666FE3F8014AE47E17AFC3FA06666666666FE3F000000000000003D1800000000000040000000000000003D18000000000000400000000000000040400000000000F03F000000000000F03F000000000000143D0000000000000040000000000000143D000000000000003D, 0);

  • Forum Etiquette: How to post Reporting Services problems
  • [/url]
  • Forum Etiquette: How to post data/code on a forum to get the best help - by Jeff Moden
  • [/url]
  • How to Post Performance Problems - by Gail Shaw
  • [/url]

    Viewing 14 posts - 1 through 13 (of 13 total)

    You must be logged in to reply to this topic. Login to reply