4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give.
11 ******************************************************************************
13 ** This SQLite extension implements functions that handling RFC-4122 UUIDs
14 ** Three SQL functions are implemented:
16 ** uuid() - generate a version 4 UUID as a string
17 ** uuid_str(X) - convert a UUID X into a well-formed UUID string
18 ** uuid_blob(X) - convert a UUID X into a 16-byte blob
20 ** The output from uuid() and uuid_str(X) are always well-formed RFC-4122
21 ** UUID strings in this format:
23 ** xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
25 ** All of the 'x', 'M', and 'N' values are lower-case hexadecimal digits.
26 ** The M digit indicates the "version". For uuid()-generated UUIDs, the
27 ** version is always "4" (a random UUID). The upper three bits of N digit
28 ** are the "variant". This library only supports variant 1 (indicated
29 ** by values of N between '8' and 'b') as those are overwhelming the most
30 ** common. Other variants are for legacy compatibility only.
32 ** The output of uuid_blob(X) is always a 16-byte blob. The UUID input
33 ** string is converted in network byte order (big-endian) in accordance
34 ** with RFC-4122 specifications for variant-1 UUIDs. Note that network
35 ** byte order is *always* used, even if the input self-identifies as a
38 ** The input X to the uuid_str() and uuid_blob() functions can be either
39 ** a string or a BLOB. If it is a BLOB it must be exactly 16 bytes in
40 ** length or else a NULL is returned. If the input is a string it must
41 ** consist of 32 hexadecimal digits, upper or lower case, optionally
42 ** surrounded by {...} and with optional "-" characters interposed in the
43 ** middle. The flexibility of input is inspired by the PostgreSQL
44 ** implementation of UUID functions that accept in all of the following
47 ** A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
48 ** {a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
49 ** a0eebc999c0b4ef8bb6d6bb9bd380a11
50 ** a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
51 ** {a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}
53 ** If any of the above inputs are passed into uuid_str(), the output will
54 ** always be in the canonical RFC-4122 format:
56 ** a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
58 ** If the X input string has too few or too many digits or contains
59 ** stray characters other than {, }, or -, then NULL is returned.
61 #include "sqlite3ext.h"
62 SQLITE_EXTENSION_INIT1
67 #if !defined(SQLITE_ASCII) && !defined(SQLITE_EBCDIC)
68 # define SQLITE_ASCII 1
72 ** Translate a single byte of Hex into an integer.
73 ** This routine only works if h really is a valid hexadecimal
74 ** character: 0..9a..fA..F
76 static unsigned char sqlite3UuidHexToInt(int h
){
77 assert( (h
>='0' && h
<='9') || (h
>='a' && h
<='f') || (h
>='A' && h
<='F') );
84 return (unsigned char)(h
& 0xf);
88 ** Convert a 16-byte BLOB into a well-formed RFC-4122 UUID. The output
89 ** buffer zStr should be at least 37 bytes in length. The output will
90 ** be zero-terminated.
92 static void sqlite3UuidBlobToStr(
93 const unsigned char *aBlob
, /* Input blob */
94 unsigned char *zStr
/* Write the answer here */
96 static const char zDigits
[] = "0123456789abcdef";
100 for(i
=0, k
=0x550; i
<16; i
++, k
=k
>>1){
106 zStr
[0] = zDigits
[x
>>4];
107 zStr
[1] = zDigits
[x
&0xf];
114 ** Attempt to parse a zero-terminated input string zStr into a binary
115 ** UUID. Return 0 on success, or non-zero if the input string is not
118 static int sqlite3UuidStrToBlob(
119 const unsigned char *zStr
, /* Input string */
120 unsigned char *aBlob
/* Write results here */
123 if( zStr
[0]=='{' ) zStr
++;
125 if( zStr
[0]=='-' ) zStr
++;
126 if( isxdigit(zStr
[0]) && isxdigit(zStr
[1]) ){
127 aBlob
[i
] = (sqlite3UuidHexToInt(zStr
[0])<<4)
128 + sqlite3UuidHexToInt(zStr
[1]);
134 if( zStr
[0]=='}' ) zStr
++;
139 ** Render sqlite3_value pIn as a 16-byte UUID blob. Return a pointer
140 ** to the blob, or NULL if the input is not well-formed.
142 static const unsigned char *sqlite3UuidInputToBlob(
143 sqlite3_value
*pIn
, /* Input text */
144 unsigned char *pBuf
/* output buffer */
146 switch( sqlite3_value_type(pIn
) ){
148 const unsigned char *z
= sqlite3_value_text(pIn
);
149 if( sqlite3UuidStrToBlob(z
, pBuf
) ) return 0;
153 int n
= sqlite3_value_bytes(pIn
);
154 return n
==16 ? sqlite3_value_blob(pIn
) : 0;
162 /* Implementation of uuid() */
163 static void sqlite3UuidFunc(
164 sqlite3_context
*context
,
168 unsigned char aBlob
[16];
169 unsigned char zStr
[37];
172 sqlite3_randomness(16, aBlob
);
173 aBlob
[6] = (aBlob
[6]&0x0f) + 0x40;
174 aBlob
[8] = (aBlob
[8]&0x3f) + 0x80;
175 sqlite3UuidBlobToStr(aBlob
, zStr
);
176 sqlite3_result_text(context
, (char*)zStr
, 36, SQLITE_TRANSIENT
);
179 /* Implementation of uuid_str() */
180 static void sqlite3UuidStrFunc(
181 sqlite3_context
*context
,
185 unsigned char aBlob
[16];
186 unsigned char zStr
[37];
187 const unsigned char *pBlob
;
189 pBlob
= sqlite3UuidInputToBlob(argv
[0], aBlob
);
190 if( pBlob
==0 ) return;
191 sqlite3UuidBlobToStr(pBlob
, zStr
);
192 sqlite3_result_text(context
, (char*)zStr
, 36, SQLITE_TRANSIENT
);
195 /* Implementation of uuid_blob() */
196 static void sqlite3UuidBlobFunc(
197 sqlite3_context
*context
,
201 unsigned char aBlob
[16];
202 const unsigned char *pBlob
;
204 pBlob
= sqlite3UuidInputToBlob(argv
[0], aBlob
);
205 if( pBlob
==0 ) return;
206 sqlite3_result_blob(context
, pBlob
, 16, SQLITE_TRANSIENT
);
210 __declspec(dllexport
)
212 int sqlite3_uuid_init(
215 const sqlite3_api_routines
*pApi
218 SQLITE_EXTENSION_INIT2(pApi
);
219 (void)pzErrMsg
; /* Unused parameter */
220 rc
= sqlite3_create_function(db
, "uuid", 0, SQLITE_UTF8
|SQLITE_INNOCUOUS
, 0,
221 sqlite3UuidFunc
, 0, 0);
223 rc
= sqlite3_create_function(db
, "uuid_str", 1,
224 SQLITE_UTF8
|SQLITE_INNOCUOUS
|SQLITE_DETERMINISTIC
,
225 0, sqlite3UuidStrFunc
, 0, 0);
228 rc
= sqlite3_create_function(db
, "uuid_blob", 1,
229 SQLITE_UTF8
|SQLITE_INNOCUOUS
|SQLITE_DETERMINISTIC
,
230 0, sqlite3UuidBlobFunc
, 0, 0);