2012-09-06 9 views
5

Mi aplicación utiliza internamente GUÍAS SIN PROCESAR (16) generadas a través de sys_guid().
Recientemente comencé a asociar usuarios de Active Directory donde obtengo los guid en el formato de: 00000000-0000-0000-0000-00000000000GUIDTORAW de Oracle y endianness de la función RAWTOGUID

¿Las dos funciones siguientes están haciendo esta conversión correctamente?

encontró el siguiente sitio:

http://www.timvasil.com/blog14/post/2009/01/20/User-defined-function-to-convert-from-RAW(16)-to-a-GUID-in-Oracle.aspx

create or replace 
FUNCTION RAWTOGUID 
(RawData IN RAW 
) RETURN VARCHAR AS 

BEGIN 

declare HexData varchar(32) := rawtohex(RawData); 

begin 
return 
    substr(HexData, 7, 2) 
    || substr(HexData, 5, 2) 
    || substr(HexData, 3, 2) 
    || substr(HexData, 1, 2) 
    || '-' 
    || substr(HexData, 11, 2) 
    || substr(HexData, 9, 2) 
    || '-' 
    || substr(HexData, 15, 2) 
    || substr(HexData, 13, 2) 
    || '-' 
    || substr(HexData, 17, 4) 
    || '-' 
    || substr(HexData, 21, 12); 
end; 

END RAWTOGUID; 

Adición en el siguiente sitio:

http://dbaspot.com/oracle-server/69226-guid-char-conversion-function.html

ocurrió esta función para hacer el inverso:

create or replace 
FUNCTION GUIDTORAW 
(HexData IN VARCHAR 
) RETURN RAW AS 

BEGIN 

declare StringData varchar(32) := TRANSLATE(HexData,'0{-}','0'); 

begin 

return 
    hextoraw(substr(StringData, 7, 2) 
    || substr(StringData, 5, 2) 
    || substr(StringData, 3, 2) 
    || substr(StringData, 1, 2) 
    || substr(StringData, 11, 2) 
    || substr(StringData, 9, 2) 
    || substr(StringData, 15, 2) 
    || substr(StringData, 13, 2) 
    || substr(StringData, 17, 4) 
    || substr(StringData, 21, 12)); 
end; 

END GUIDTORAW; 

Se convierten de ida y vuelta, pero ¿de verdad estoy respetando la endianidad o tengo el orden correcto?

+0

He comparado los resultados de la función RAWTOGUID() con el método .NET Guid.ToByteArray(), insertando en Oracle como byte [], ejecutando RAWTOGUID() vs Guid.ToString() y obteniendo los mismos resultados. Si ha probado que GUIDTORAW() es realmente el reverso de RAWTOGUID(), entonces parece que las funciones son correctas. Sin embargo, preferiría revisar las especificaciones del pedido de bytes de Guid y compararlas. –

+0

Relacionados: http://stackoverflow.com/questions/7289734/convert-from-oracles-raw16-to-nets-guid y http://stackoverflow.com/questions/9195551/why-does-guid-tobytearray-order -the-bytes-the-way-it-do –

Respuesta

5

Citando del UUID standard:

La estructura de UUID es:

 
    Field     Data Type  Octet Note 
             # 

    time_low    unsigned 32 0-3 The low field of the 
          bit integer   timestamp 

    time_mid    unsigned 16 4-5 The middle field of the 
          bit integer   timestamp 

    time_hi_and_version unsigned 16 6-7 The high field of the 
          bit integer   timestamp multiplexed 
               with the version number 

    clock_seq_hi_and_rese unsigned 8 8  The high field of the 
    rved     bit integer   clock sequence 
               multiplexed with the 
               variant 

    clock_seq_low   unsigned 8 9  The low field of the 
          bit integer   clock sequence 

    node     unsigned 48 10-15 The spatially unique 
          bit integer   node identifier 

En ausencia de aplicación explícita o protocolo de presentación especificación en contrario, un UUID se codifica como una de 128 bits objeto, como sigue:

Los campos están codificados como 16 octetos, con los tamaños y el orden de los campos definidos anteriormente, y con cada fie ld codificado con el Byte significativo primero (conocido como orden de bytes de red). Tenga en cuenta que los nombres de campo , particularmente para campos multiplexados, siguen la práctica histórica .

 
    0     1     2     3 
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
    |       time_low        | 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
    |  time_mid    |   time_hi_and_version | 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
    |clk_seq_hi_res | clk_seq_low |   node (0-1)   | 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
    |       node (2-5)       | 
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 

Citando del Guid documentation:

public Guid(int a, short b, short c, byte[] d) 

Guid(1,2,3,new byte[]{0,1,2,3,4,5,6,7}) 
creates a Guid that corresponds to "00000001-0002-0003-0001-020304050607". 

Según Wikipedia's Endianness article Windows almacena números en Little Endian -> byte menos significativo primero.

El mapeo 1,2,3, nuevo byte [] {0,1,2,3,4,5,6,7} a "00000001-0002-0003-0001-020304050607", nos muestra que el los números se muestran big-endian, como en el estándar UUID; sin embargo, la matriz de bytes se proporciona en el mismo orden que la visualización, no es necesario intercambiar los bytes.

Así GUID se muestra como:

{Time_Low (4B) - time_mid (2B) - time_hi_and_version (2B) - clock_sq_hi_and_reserved (1B), clock_seq_low (1B) - nodo (6B)}

En little endian esto da como resultado un orden de bytes (byte [] no cuenta como un número como por lo tanto:

{3,2,1,0 - 5,4 - 7,6 - 8,9 - 10,11, 12,13,14,15}

que da como resultado el orden de caracteres hexadecimales (cada byte tiene 2 dígitos hexadecimales):

{6,7,4,5,2,3,0,1 - 10,11,8,9 - 14,15,12,13 - 16,17,18,19 - 20,21,22 , 23,24,25,26,27,28,29,30,31}

En Oracle, el substr string function es 1-basada, por lo tanto, los índices de cadenas de Oracle son:

{7,8,5 , 6,3,4,1,2 - 11,12,9,10 - 15,16,13,14 - 17,18,19,20 - 21,22,23,24,25,26,27,28 , 29,30,31,32}

que se traduce en el comando

substr(HexData, 7, 2) 
|| substr(HexData, 5, 2) 
|| substr(HexData, 3, 2) 
|| substr(HexData, 1, 2) 
|| '-' 
|| substr(HexData, 11, 2) 
|| substr(HexData, 9, 2) 
|| '-' 
|| substr(HexData, 15, 2) 
|| substr(HexData, 13, 2) 
|| '-' 
|| substr(HexData, 17, 4) 
|| '-' 
|| substr(HexData, 21, 12); 

Y transpuesta (después de eliminar '-'s):

{7,8,5,6,3,4,1,2, 11,12,9,10, 15,16,13,14, 17 , 18,19,20, 21,22,23,24,25,26,27,28,29,30,31,32}

se invierte de nuevo en

{1,2,3, 4,5,6,7,8, 9,10,11,12, 13,14,15,16, 17,18,19,20, 21,22,23,24,25,26,27,28, 29,30,31,32}

usando la misma función (sin agregar '-'s) - la conversión de BE en LE y LE en BE tiene los mismos intercambios ya que los bytes simplemente se invierten y la inversión de bytes invertidos da como resultado no bytes invertidos.

Cuestiones relacionadas