Changeset: 1b56cc8e870c for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=1b56cc8e870c Modified Files: clients/odbc/driver/ODBCConvert.c clients/odbc/driver/ODBCUtil.c common/utils/muuid.c monetdb5/modules/atoms/uuid.c Branch: linear-hashing Log Message:
Use uuid library when available; fix ODBC roundtrip of UUID values. We don't use the uuid library for parsing UUID strings (uuid_parse) since we want to accept UUID strings without hyphens. diffs (truncated from 427 to 300 lines): diff --git a/clients/odbc/driver/ODBCConvert.c b/clients/odbc/driver/ODBCConvert.c --- a/clients/odbc/driver/ODBCConvert.c +++ b/clients/odbc/driver/ODBCConvert.c @@ -39,6 +39,15 @@ typedef struct { #endif } bignum_t; +typedef union { + SQLGUID g; + struct { + uint32_t d1; + uint16_t d2, d3; + uint8_t d4[8]; + } d; +} uuid_t; + /* Parse a number and store in a bignum_t. * 1 is returned if all is well; * 2 is returned if there is loss of precision (i.e. overflow of the value); @@ -2795,44 +2804,22 @@ ODBCFetch(ODBCStmt *stmt, #ifdef ODBCDEBUG ODBCLOG("Writing 16 bytes to %p\n", ptr); #endif - for (i = 0; i < 16; i++) { - if (i == 8 || i == 12 || i == 16 || i == 20) { - if (*data != '-') { - /* Restricted data type - * attribute violation */ - addStmtError(stmt, "07006", NULL, 0); - return SQL_ERROR; - } - data++; - } - if (isdigit((unsigned char) *data)) - ((unsigned char *) ptr)[i] = *data - '0'; - else if ('a' <= *data && *data <= 'f') - ((unsigned char *) ptr)[i] = *data - 'a' + 10; - else if ('A' <= *data && *data <= 'F') - ((unsigned char *) ptr)[i] = *data - 'A' + 10; - else { - /* Restricted data type attribute - * violation */ - addStmtError(stmt, "07006", NULL, 0); - return SQL_ERROR; - } - ((unsigned char *) ptr)[i] <<= 4; - data++; - if (isdigit((unsigned char) *data)) - ((unsigned char *) ptr)[i] |= *data - '0'; - else if ('a' <= *data && *data <= 'f') - ((unsigned char *) ptr)[i] |= *data - 'a' + 10; - else if ('A' <= *data && *data <= 'F') - ((unsigned char *) ptr)[i] |= *data - 'A' + 10; - else { - /* Restricted data type attribute - * violation */ - addStmtError(stmt, "07006", NULL, 0); - return SQL_ERROR; - } - data++; + uuid_t u; + if (sscanf(data, "%8"SCNx32"-%4"SCNx16"-%4"SCNx16 + "-%2"SCNx8"%2"SCNx8"-%2"SCNx8"%2"SCNx8 + "%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8, + &u.d.d1, &u.d.d2, &u.d.d3, &u.d.d4[0], + &u.d.d4[1], &u.d.d4[2], &u.d.d4[3], + &u.d.d4[4], &u.d.d4[5], &u.d.d4[6], + &u.d.d4[7]) != 11) { + /* Restricted data type attribute + * violation */ + addStmtError(stmt, "07006", NULL, 0); + return SQL_ERROR; } + WriteData(ptr, u.g, SQLGUID); + if (lenp) + *lenp = sizeof(SQLGUID); break; default: /* Invalid application buffer type */ @@ -2902,6 +2889,7 @@ ODBCStore(ODBCStmt *stmt, TIMESTAMP_STRUCT tsval; int ivalprec = 0; /* interval second precision */ SQL_INTERVAL_STRUCT ival; + uuid_t u; char *buf = *bufp; size_t bufpos = *bufposp; size_t buflen = *buflenp; @@ -3365,25 +3353,16 @@ ODBCStore(ODBCStmt *stmt, } break; case SQL_C_GUID: + u.g = *(SQLGUID *)ptr; snprintf(data, sizeof(data), - "%02x%02x%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x-%02x%02x%02x%02x%02x%02x", - ((unsigned char *) ptr)[0], - ((unsigned char *) ptr)[1], - ((unsigned char *) ptr)[2], - ((unsigned char *) ptr)[3], - ((unsigned char *) ptr)[4], - ((unsigned char *) ptr)[5], - ((unsigned char *) ptr)[6], - ((unsigned char *) ptr)[7], - ((unsigned char *) ptr)[8], - ((unsigned char *) ptr)[9], - ((unsigned char *) ptr)[10], - ((unsigned char *) ptr)[11], - ((unsigned char *) ptr)[12], - ((unsigned char *) ptr)[13], - ((unsigned char *) ptr)[14], - ((unsigned char *) ptr)[15]); + "%08"PRIx32"-%04"PRIx16"-%04"PRIx16 + "-%02"PRIx8"%02"PRIx8 + "-%02"PRIx8"%02"PRIx8"%02"PRIx8 + "%02"PRIx8"%02"PRIx8"%02"PRIx8, + u.d.d1, u.d.d2, u.d.d3, u.d.d4[0], + u.d.d4[1], u.d.d4[2], u.d.d4[3], + u.d.d4[4], u.d.d4[5], u.d.d4[6], + u.d.d4[7]); break; } assign(buf, bufpos, buflen, '\'', stmt); @@ -3919,19 +3898,18 @@ ODBCStore(ODBCStmt *stmt, snprintf(data, sizeof(data), "%.36s", sval); break; case SQL_C_GUID: - snprintf(data, sizeof(data), "%08lx-%04x-%04x-%02x%02x-" - "%02x%02x%02x%02x%02x%02x", - (unsigned long) ((SQLGUID *) ptr)->Data1, - (unsigned int) ((SQLGUID *) ptr)->Data2, - (unsigned int) ((SQLGUID *) ptr)->Data3, - (unsigned int) ((SQLGUID *) ptr)->Data4[0], - (unsigned int) ((SQLGUID *) ptr)->Data4[1], - (unsigned int) ((SQLGUID *) ptr)->Data4[2], - (unsigned int) ((SQLGUID *) ptr)->Data4[3], - (unsigned int) ((SQLGUID *) ptr)->Data4[4], - (unsigned int) ((SQLGUID *) ptr)->Data4[5], - (unsigned int) ((SQLGUID *) ptr)->Data4[6], - (unsigned int) ((SQLGUID *) ptr)->Data4[7]); + u.g = *(SQLGUID *)ptr; + snprintf(data, sizeof(data), + "UUID '" + "%08"PRIx32"-%04"PRIx16"-%04"PRIx16 + "-%02"PRIx8"%02"PRIx8 + "-%02"PRIx8"%02"PRIx8"%02"PRIx8 + "%02"PRIx8"%02"PRIx8"%02"PRIx8 + "'", + u.d.d1, u.d.d2, u.d.d3, u.d.d4[0], + u.d.d4[1], u.d.d4[2], u.d.d4[3], + u.d.d4[4], u.d.d4[5], u.d.d4[6], + u.d.d4[7]); break; default: /* Restricted data type attribute violation */ diff --git a/clients/odbc/driver/ODBCUtil.c b/clients/odbc/driver/ODBCUtil.c --- a/clients/odbc/driver/ODBCUtil.c +++ b/clients/odbc/driver/ODBCUtil.c @@ -464,6 +464,11 @@ ODBCTranslateSQL(ODBCDbc *dbc, const SQL unsigned yr, mt, dy, hr, mn, sc; unsigned long fr = 0; int n, pr; + struct { + uint32_t d1; + uint16_t d2, d3; + uint8_t d4[8]; + } u; nquery = dupODBCstring(query, length); if (nquery == NULL) @@ -603,6 +608,35 @@ ODBCTranslateSQL(ODBCDbc *dbc, const SQL free(nquery); nquery = q; q += n; + } else if (sscanf(p, "guid '%8"SCNx32"-%4"SCNx16"-%4"SCNx16 + "-%2"SCNx8"%2"SCNx8"-%2"SCNx8"%2"SCNx8 + "%2"SCNx8"%2"SCNx8"%2"SCNx8"%2"SCNx8"'%n", + &u.d1, &u.d2, &u.d3, &u.d4[0], &u.d4[1], + &u.d4[2], &u.d4[3], &u.d4[4], &u.d4[5], + &u.d4[6], &u.d4[7], &n) >= 11) { + p += n; + while (*p == ' ') + p++; + if (*p != '}') + continue; + p++; + snprintf(buf, sizeof(buf), + "UUID '%08"PRIx32"-%04"PRIx16"-%04"PRIx16 + "-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8 + "%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"'", + u.d1, u.d2, u.d3, u.d4[0], u.d4[1], u.d4[2], + u.d4[3], u.d4[4], u.d4[5], u.d4[6], u.d4[7]); + n = (int) (q - nquery); + pr = (int) (p - q); + q = malloc(length - pr + strlen(buf) + 1); + if (q == NULL) { + free(nquery); + return NULL; + } + length = (size_t) sprintf(q, "%.*s%s%s", n, nquery, buf, p); + free(nquery); + nquery = q; + q += n; } else if (strncasecmp(p, "escape ", 7) == 0) { /* note that in ODBC the syntax is * {escape '\'} diff --git a/common/utils/muuid.c b/common/utils/muuid.c --- a/common/utils/muuid.c +++ b/common/utils/muuid.c @@ -49,7 +49,11 @@ generateUUID(void) char out[37]; #ifdef HAVE_OPENSSL unsigned char randbuf[16]; - if (RAND_bytes(randbuf, 16) >= 0) + if (RAND_bytes(randbuf, 16) >= 0) { + /* make sure this is a variant 1 UUID (RFC 4122/DCE 1.1) */ + randbuf[8] = (randbuf[8] & 0x3F) | 0x80; + /* make sure this is version 4 (random UUID) */ + randbuf[6] = (randbuf[6] & 0x0F) | 0x40; snprintf(out, sizeof(out), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" "%02x%02x%02x%02x%02x%02x", @@ -57,11 +61,15 @@ generateUUID(void) randbuf[4], randbuf[5], randbuf[6], randbuf[7], randbuf[8], randbuf[9], randbuf[10], randbuf[11], randbuf[12], randbuf[13], randbuf[14], randbuf[15]); - else + } else #else #ifdef HAVE_COMMONCRYPTO unsigned char randbuf[16]; - if (CCRandomGenerateBytes(randbuf, 16) == kCCSuccess) + if (CCRandomGenerateBytes(randbuf, 16) == kCCSuccess) { + /* make sure this is a variant 1 UUID (RFC 4122/DCE 1.1) */ + randbuf[8] = (randbuf[8] & 0x3F) | 0x80; + /* make sure this is version 4 (random UUID) */ + randbuf[6] = (randbuf[6] & 0x0F) | 0x40; snprintf(out, sizeof(out), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" "%02x%02x%02x%02x%02x%02x", @@ -69,18 +77,20 @@ generateUUID(void) randbuf[4], randbuf[5], randbuf[6], randbuf[7], randbuf[8], randbuf[9], randbuf[10], randbuf[11], randbuf[12], randbuf[13], randbuf[14], randbuf[15]); - else + } else #endif #endif + { /* generate something like this: - * cefa7a9c-1dd2-11b2-8350-880020adbeef + * cefa7a9c-1dd2-41b2-8350-880020adbeef * ("%08x-%04x-%04x-%04x-%012x") */ snprintf(out, sizeof(out), - "%04x%04x-%04x-%04x-%04x-%04x%04x%04x", - rand() % 65536, rand() % 65536, + "%04x%04x-%04x-4%03x-8%03x-%04x%04x%04x", rand() % 65536, rand() % 65536, - rand() % 65536, rand() % 65536, + rand() % 65536, rand() % 4096, + rand() % 4096, rand() % 65536, rand() % 65536, rand() % 65536); + } #endif return strdup(out); } diff --git a/monetdb5/modules/atoms/uuid.c b/monetdb5/modules/atoms/uuid.c --- a/monetdb5/modules/atoms/uuid.c +++ b/monetdb5/modules/atoms/uuid.c @@ -46,7 +46,7 @@ typedef union { #ifdef HAVE_UUID uuid_t u; #else - unsigned char u[UUID_SIZE]; + uint8_t u[UUID_SIZE]; #endif } uuid; @@ -84,10 +84,17 @@ UUIDprelude(void *ret) #ifdef HAVE_HGE BATatoms[u].storage = TYPE_hge; #endif +#ifdef HAVE_UUID + uuid_clear(uuid_nil.u); +#endif return MAL_SUCCEED; } +#ifdef HAVE_UUID +#define is_uuid_nil(x) uuid_is_null((x)->u) +#else #define is_uuid_nil(x) (memcmp((x)->u, uuid_nil.u, UUID_SIZE) == 0) +#endif /** * Returns the string representation of the given uuid value. @@ -106,18 +113,21 @@ UUIDtoString(str *retval, size_t *len, c } if (is_uuid_nil(value)) { if (external) { - snprintf(*retval, *len, "nil"); _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list