| 
      
      
      From: <asf...@us...> - 2011-12-21 14:45:50
      
     | 
| Revision: 53728
          http://firebird.svn.sourceforge.net/firebird/?rev=53728&view=rev
Author:   asfernandes
Date:     2011-12-21 14:45:39 +0000 (Wed, 21 Dec 2011)
Log Message:
-----------
Backport CORE-3238 - Make GEN_UUID return a compliant RFC-4122 binary UUID and introduce CHAR_TO_UUID2 and UUID_TO_CHAR2 to convert UUIDs from/to string also complying with the RFC.
Modified Paths:
--------------
    firebird/branches/B2_5_Release/builds/make.new/config/install-sh
    firebird/branches/B2_5_Release/doc/sql.extensions/README.builtin_functions.txt
    firebird/branches/B2_5_Release/src/dsql/keywords.cpp
    firebird/branches/B2_5_Release/src/dsql/parse.y
    firebird/branches/B2_5_Release/src/jrd/SysFunction.cpp
    firebird/branches/B2_5_Release/src/jrd/os/guid.h
    firebird/branches/B2_5_Release/src/jrd/os/posix/guid.cpp
Property Changed:
----------------
    firebird/branches/B2_5_Release/builds/make.new/config/install-sh
Property changes on: firebird/branches/B2_5_Release/builds/make.new/config/install-sh
___________________________________________________________________
Added: svn:executable
   + *
Modified: firebird/branches/B2_5_Release/doc/sql.extensions/README.builtin_functions.txt
===================================================================
--- firebird/branches/B2_5_Release/doc/sql.extensions/README.builtin_functions.txt	2011-12-21 10:57:15 UTC (rev 53727)
+++ firebird/branches/B2_5_Release/doc/sql.extensions/README.builtin_functions.txt	2011-12-21 14:45:39 UTC (rev 53728)
@@ -246,12 +246,38 @@
 Format:
     CHAR_TO_UUID( <string> )
 
+Notes:
+    If you have not used this function before, its usage is discouraged. CHAR_TO_UUID2 superseds it.
+
 Example:
     select char_to_uuid('93519227-8D50-4E47-81AA-8F6678C096A1') from rdb$database;
 
-See also: GEN_UUID and UUID_TO_CHAR
+See also: GEN_UUID, CHAR_TO_UUID2, UUID_TO_CHAR and UUID_TO_CHAR2
 
 
+-------------
+CHAR_TO_UUID2
+-------------
+
+Function:
+    Converts the CHAR(32) ASCII representation of an UUID
+    (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX) to the CHAR(16) OCTETS
+    representation (optimized for storage).
+
+Format:
+    CHAR_TO_UUID2( <string> )
+
+Notes:
+    This function superseds CHAR_TO_UUID. The difference between them is that CHAR_TO_UUID does a
+    byte-by-byte conversion of the ASCII string to the OCTETS one, while CHAR_TO_UUID2 converts
+    a RFC-4122 compliant ASCII UUID to a compliant OCTETS string.
+
+Example:
+    select char_to_uuid2('93519227-8D50-4E47-81AA-8F6678C096A1') from rdb$database;
+
+See also: GEN_UUID, UUID_TO_CHAR2
+
+
 ---
 COS
 ---
@@ -405,10 +431,17 @@
 Format:
     GEN_UUID()
 
+Notes:
+    In Firebird 2.5.0 and 2.5.1, GEN_UUID was returning completely random strings. This is not
+    compliant with the RFC-4122 (UUID specification).
+    In Firebird 2.5.2 and 3.0 this was fixed. Now GEN_UUID returns a compliant UUID version 4
+    string, where some bits are reserved and the others are random. The string format of a compliant
+    UUID is XXXXXXXX-XXXX-4XXX-YXXX-XXXXXXXXXXXX, where 4 is fixed (version) and Y is 8, 9, A or B.
+
 Example:
     insert into records (id) value (gen_uuid());
 
-See also: CHAR_TO_UUID and UUID_TO_CHAR
+See also: CHAR_TO_UUID, UUID_TO_CHAR, CHAR_TO_UUID2, UUID_TO_CHAR2
 
 
 ----
@@ -836,7 +869,32 @@
 Format:
     UUID_TO_CHAR( <string> )
 
+Notes:
+    If you have not used this function before, its usage is discouraged. UUID_TO_CHAR2 superseds it.
+
 Example:
     select uuid_to_char(gen_uuid()) from rdb$database;
 
-See also: GEN_UUID and CHAR_TO_UUID
+See also: GEN_UUID, UUID_TO_CHAR2, CHAR_TO_UUID and CHAR_TO_UUID2
+
+
+-------------
+UUID_TO_CHAR2
+-------------
+
+Function:
+    Converts a CHAR(16) OCTETS UUID (that's returned by GEN_UUID) to the
+    CHAR(32) ASCII representation (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX).
+
+Format:
+    UUID_TO_CHAR2( <string> )
+
+Notes:
+    This function superseds UUID_TO_CHAR. The difference between them is that UUID_TO_CHAR does a
+    byte-by-byte conversion of the OCTETS string to the ASCII one, while UUID_TO_CHAR2 converts
+    a RFC-4122 compliant OCTETS UUID to a compliant ASCII string.
+
+Example:
+    select uuid_to_char2(gen_uuid()) from rdb$database;
+
+See also: GEN_UUID, CHAR_TO_UUID2
Modified: firebird/branches/B2_5_Release/src/dsql/keywords.cpp
===================================================================
--- firebird/branches/B2_5_Release/src/dsql/keywords.cpp	2011-12-21 10:57:15 UTC (rev 53727)
+++ firebird/branches/B2_5_Release/src/dsql/keywords.cpp	2011-12-21 14:45:39 UTC (rev 53728)
@@ -104,6 +104,7 @@
 	{KW_CHAR, "CHAR", 1, false},
 	{CHAR_LENGTH, "CHAR_LENGTH", 2, false},
 	{CHAR_TO_UUID, "CHAR_TO_UUID", 2, false},
+	{CHAR_TO_UUID2, "CHAR_TO_UUID2", 2, false},
 	{CHARACTER, "CHARACTER", 1, false},
 	{CHARACTER_LENGTH, "CHARACTER_LENGTH", 2, false},
 	{CHECK, "CHECK", 1, false},
@@ -383,6 +384,7 @@
 	{USER, "USER", 1, false},
 	{USING, "USING", 2, false},
 	{UUID_TO_CHAR, "UUID_TO_CHAR", 2, false},
+	{UUID_TO_CHAR2, "UUID_TO_CHAR2", 2, false},
 	{KW_VALUE, "VALUE", 1, false},
 	{VALUES, "VALUES", 1, false},
 	{VARCHAR, "VARCHAR", 1, false},
Modified: firebird/branches/B2_5_Release/src/dsql/parse.y
===================================================================
--- firebird/branches/B2_5_Release/src/dsql/parse.y	2011-12-21 10:57:15 UTC (rev 53727)
+++ firebird/branches/B2_5_Release/src/dsql/parse.y	2011-12-21 14:45:39 UTC (rev 53728)
@@ -543,6 +543,7 @@
 
 %token AUTONOMOUS
 %token CHAR_TO_UUID
+%token CHAR_TO_UUID2
 %token FIRSTNAME
 %token GRANTED
 %token LASTNAME
@@ -551,6 +552,7 @@
 %token OS_NAME
 %token SIMILAR
 %token UUID_TO_CHAR
+%token UUID_TO_CHAR2
 
 %token DUMP
 
@@ -4639,6 +4641,7 @@
 	| BIN_XOR
 	| CEIL
 	| CHAR_TO_UUID
+	| CHAR_TO_UUID2
 	| COS
 	| COSH
 	| COT
@@ -4671,6 +4674,7 @@
 	| TANH
 	| TRUNC
 	| UUID_TO_CHAR
+	| UUID_TO_CHAR2
 	;
 
 system_function_special_syntax
@@ -5073,12 +5077,14 @@
 	| WEEK
 	| AUTONOMOUS			// added in FB 2.5
 	| CHAR_TO_UUID
+	| CHAR_TO_UUID2
 	| FIRSTNAME
 	| MIDDLENAME
 	| LASTNAME
 	| MAPPING
 	| OS_NAME
 	| UUID_TO_CHAR
+	| UUID_TO_CHAR2
 	| GRANTED
 	| CALLER				// new execute statement
 	| COMMON
Modified: firebird/branches/B2_5_Release/src/jrd/SysFunction.cpp
===================================================================
--- firebird/branches/B2_5_Release/src/jrd/SysFunction.cpp	2011-12-21 10:57:15 UTC (rev 53727)
+++ firebird/branches/B2_5_Release/src/jrd/SysFunction.cpp	2011-12-21 14:45:39 UTC (rev 53728)
@@ -68,7 +68,9 @@
 	funLPad,
 	funRPad,
 	funLnat,
-	funLog10
+	funLog10,
+	funUuidBroken,
+	funUuidRfc
 };
 
 enum TrigonFunction
@@ -1432,8 +1434,37 @@
 	memcpy(buffer + 1, data, GUID_BODY_SIZE);
 
 	FB_GUID guid;
-	StringToGuid(&guid, buffer, false);
 
+	switch ((Function)(IPTR) function->misc)
+	{
+		case funUuidBroken:
+			StringToGuid(&guid, buffer, false);
+			break;
+
+		case funUuidRfc:
+		{
+			USHORT bytes[16];
+			sscanf(buffer, GUID_NEW_FORMAT,
+				&bytes[0], &bytes[1], &bytes[2], &bytes[3],
+				&bytes[4], &bytes[5], &bytes[6], &bytes[7],
+				&bytes[8], &bytes[9], &bytes[10], &bytes[11],
+				&bytes[12], &bytes[13], &bytes[14], &bytes[15]);
+
+			guid.data1 = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
+			guid.data2 = (bytes[4] << 8) | bytes[5];
+			guid.data3 = (bytes[6] << 8) | bytes[7];
+			guid.data4[0] = bytes[8];
+			guid.data4[1] = bytes[9];
+			guid.data4[2] = bytes[10];
+			guid.data4[3] = bytes[11];
+			guid.data4[4] = bytes[12];
+			guid.data4[5] = bytes[13];
+			guid.data4[6] = bytes[14];
+			guid.data4[7] = bytes[15];
+			break;
+		}
+	}
+
 	dsc result;
 	result.makeText(16, ttype_binary, reinterpret_cast<UCHAR*>(guid.data));
 	EVL_make_value(tdbb, &result, impure);
@@ -3288,9 +3319,28 @@
 										Arg::Str(function->name));
 	}
 
+	const const FB_GUID* guid = reinterpret_cast<const FB_GUID*>(data);
 	char buffer[GUID_BUFF_SIZE];
-	GuidToString(buffer, reinterpret_cast<const FB_GUID*>(data), false);
 
+	switch ((Function)(IPTR) function->misc)
+	{
+		case funUuidBroken:
+			GuidToString(buffer, guid, false);
+			break;
+
+		case funUuidRfc:
+			sprintf(buffer, GUID_NEW_FORMAT,
+				USHORT((guid->data1 >> 24) & 0xFF), USHORT((guid->data1 >> 16) & 0xFF),
+				USHORT((guid->data1 >> 8) & 0xFF), USHORT(guid->data1 & 0xFF),
+				USHORT((guid->data2 >> 8) & 0xFF), USHORT(guid->data2 & 0xFF),
+				USHORT((guid->data3 >> 8) & 0xFF), USHORT(guid->data3 & 0xFF),
+				USHORT(guid->data4[0]), USHORT(guid->data4[1]),
+				USHORT(guid->data4[2]), USHORT(guid->data4[3]),
+				USHORT(guid->data4[4]), USHORT(guid->data4[5]),
+				USHORT(guid->data4[6]), USHORT(guid->data4[7]));
+			break;
+	}
+
 	dsc result;
 	result.makeText(GUID_BODY_SIZE, ttype_ascii, reinterpret_cast<UCHAR*>(buffer) + 1);
 	EVL_make_value(tdbb, &result, impure);
@@ -3324,7 +3374,8 @@
 		{"BIN_XOR", 2, -1, setParamsInteger, makeBin, evlBin, (void*) funBinXor},
 		{"CEIL", 1, 1, setParamsDouble, makeCeilFloor, evlCeil, NULL},
 		{"CEILING", 1, 1, setParamsDouble, makeCeilFloor, evlCeil, NULL},
-		{"CHAR_TO_UUID", 1, 1, setParamsCharToUuid, makeUuid, evlCharToUuid, NULL},
+		{"CHAR_TO_UUID", 1, 1, setParamsCharToUuid, makeUuid, evlCharToUuid, (void*) funUuidBroken},
+		{"CHAR_TO_UUID2", 1, 1, setParamsCharToUuid, makeUuid, evlCharToUuid, (void*) funUuidRfc},
 		{"COS", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCos},
 		{"COSH", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCosh},
 		{"COT", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfCot},
@@ -3359,7 +3410,8 @@
 		{"TAN", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfTan},
 		{"TANH", 1, 1, setParamsDouble, makeDoubleResult, evlStdMath, (void*) trfTanh},
 		{"TRUNC", 1, 2, setParamsRoundTrunc, makeTrunc, evlTrunc, NULL},
-		{"UUID_TO_CHAR", 1, 1, setParamsUuidToChar, makeUuidToChar, evlUuidToChar, NULL},
+		{"UUID_TO_CHAR", 1, 1, setParamsUuidToChar, makeUuidToChar, evlUuidToChar, (void*) funUuidBroken},
+		{"UUID_TO_CHAR2", 1, 1, setParamsUuidToChar, makeUuidToChar, evlUuidToChar, (void*) funUuidRfc},
 		{"", 0, 0, NULL, NULL, NULL, NULL}
 	};
 
Modified: firebird/branches/B2_5_Release/src/jrd/os/guid.h
===================================================================
--- firebird/branches/B2_5_Release/src/jrd/os/guid.h	2011-12-21 10:57:15 UTC (rev 53727)
+++ firebird/branches/B2_5_Release/src/jrd/os/guid.h	2011-12-21 14:45:39 UTC (rev 53728)
@@ -44,7 +44,18 @@
 
 struct FB_GUID
 {
-	USHORT data[8];
+	union
+	{
+		USHORT data[8];
+
+		struct	// Compatible with Win32 GUID struct layout.
+		{
+			ULONG data1;
+			USHORT data2;
+			USHORT data3;
+			UCHAR data4[8];
+		};
+	};
 };
 
 void GenerateRandomBytes(void* buffer, size_t size);
@@ -63,14 +74,14 @@
 	else
 	{
 		sprintf(buffer, GUID_NEW_FORMAT,
-			guid->data[0] & 0xFF, guid->data[0] >> 8,
-			guid->data[1] & 0xFF, guid->data[1] >> 8,
-			guid->data[2] & 0xFF, guid->data[2] >> 8,
-			guid->data[3] & 0xFF, guid->data[3] >> 8,
-			guid->data[4] & 0xFF, guid->data[4] >> 8,
-			guid->data[5] & 0xFF, guid->data[5] >> 8,
-			guid->data[6] & 0xFF, guid->data[6] >> 8,
-			guid->data[7] & 0xFF, guid->data[7] >> 8);
+			USHORT(guid->data[0] & 0xFF), USHORT(guid->data[0] >> 8),
+			USHORT(guid->data[1] & 0xFF), USHORT(guid->data[1] >> 8),
+			USHORT(guid->data[2] & 0xFF), USHORT(guid->data[2] >> 8),
+			USHORT(guid->data[3] & 0xFF), USHORT(guid->data[3] >> 8),
+			USHORT(guid->data[4] & 0xFF), USHORT(guid->data[4] >> 8),
+			USHORT(guid->data[5] & 0xFF), USHORT(guid->data[5] >> 8),
+			USHORT(guid->data[6] & 0xFF), USHORT(guid->data[6] >> 8),
+			USHORT(guid->data[7] & 0xFF), USHORT(guid->data[7] >> 8));
 	}
 }
 
Modified: firebird/branches/B2_5_Release/src/jrd/os/posix/guid.cpp
===================================================================
--- firebird/branches/B2_5_Release/src/jrd/os/posix/guid.cpp	2011-12-21 10:57:15 UTC (rev 53727)
+++ firebird/branches/B2_5_Release/src/jrd/os/posix/guid.cpp	2011-12-21 14:45:39 UTC (rev 53728)
@@ -70,4 +70,6 @@
 void GenerateGuid(FB_GUID* guid)
 {
 	GenerateRandomBytes(guid, sizeof(FB_GUID));
+	guid->data3 = (4 << 12) | (guid->data3 & 0xFFF);	// version 4
+	guid->data4[0] = 0x80 | (guid->data4[0] & 0x3F);	// variant
 }
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 |