diff options
Diffstat (limited to 'sql/item_strfunc.cc')
-rw-r--r-- | sql/item_strfunc.cc | 169 |
1 files changed, 16 insertions, 153 deletions
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index ed14f7f01e9..60d5d2f1341 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2011, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -120,7 +120,6 @@ String *Item_func_md5::val_str(String *str) { DBUG_ASSERT(fixed == 1); String * sptr= args[0]->val_str(str); - str->set_charset(&my_charset_bin); if (sptr) { uchar digest[16]; @@ -133,6 +132,7 @@ String *Item_func_md5::val_str(String *str) return 0; } array_to_hex((char *) str->ptr(), (const char*) digest, 16); + str->set_charset(&my_charset_bin); str->length((uint) 32); return str; } @@ -159,7 +159,6 @@ String *Item_func_sha::val_str(String *str) { DBUG_ASSERT(fixed == 1); String * sptr= args[0]->val_str(str); - str->set_charset(&my_charset_bin); if (sptr) /* If we got value different from NULL */ { SHA1_CONTEXT context; /* Context used to generate SHA1 hash */ @@ -169,11 +168,13 @@ String *Item_func_sha::val_str(String *str) /* No need to check error as the only case would be too long message */ mysql_sha1_input(&context, (const uchar *) sptr->ptr(), sptr->length()); + /* Ensure that memory is free and we got result */ if (!( str->alloc(SHA1_HASH_SIZE*2) || (mysql_sha1_result(&context,digest)))) { array_to_hex((char *) str->ptr(), (const char*) digest, SHA1_HASH_SIZE); + str->set_charset(&my_charset_bin); str->length((uint) SHA1_HASH_SIZE*2); null_value=0; return str; @@ -511,7 +512,8 @@ String *Item_func_des_encrypt::val_str(String *str) tail= 8 - (res_length % 8); // 1..8 marking extra length res_length+=tail; - tmp_arg.realloc(res_length); + if (tmp_arg.realloc(res_length)) + goto error; tmp_arg.length(0); tmp_arg.append(res->ptr(), res->length()); code= ER_OUT_OF_RESOURCES; @@ -646,7 +648,7 @@ String *Item_func_concat_ws::val_str(String *str) use_as_buff= &tmp_value; str->length(0); // QQ; Should be removed - res=str; + res=str; // If 0 arg_count // Skip until non-null argument is found. // If not, return the empty string @@ -3375,7 +3377,7 @@ longlong Item_func_crc32::val_int() String *Item_func_compress::val_str(String *str) { int err= Z_OK, code; - ulong new_size; + size_t new_size; String *res; Byte *body; char *tmp, *last_char; @@ -3411,8 +3413,8 @@ String *Item_func_compress::val_str(String *str) body= ((Byte*)buffer.ptr()) + 4; // As far as we have checked res->is_empty() we can use ptr() - if ((err= compress(body, &new_size, - (const Bytef*)res->ptr(), res->length())) != Z_OK) + if ((err= my_compress_buffer(body, &new_size, (const uchar *)res->ptr(), + res->length())) != Z_OK) { code= err==Z_MEM_ERROR ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_BUF_ERROR; push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,code,ER(code)); @@ -3490,156 +3492,17 @@ err: } #endif -/* - UUID, as in - DCE 1.1: Remote Procedure Call, - Open Group Technical Standard Document Number C706, October 1997, - (supersedes C309 DCE: Remote Procedure Call 8/1994, - which was basis for ISO/IEC 11578:1996 specification) -*/ - -static struct rand_struct uuid_rand; -static uint nanoseq; -static ulonglong uuid_time=0; -static char clock_seq_and_node_str[]="-0000-000000000000"; - -/** - number of 100-nanosecond intervals between - 1582-10-15 00:00:00.00 and 1970-01-01 00:00:00.00. -*/ -#define UUID_TIME_OFFSET ((ulonglong) 141427 * 24 * 60 * 60 * \ - 1000 * 1000 * 10) - -#define UUID_VERSION 0x1000 -#define UUID_VARIANT 0x8000 - -static void tohex(char *to, uint from, uint len) -{ - to+= len; - while (len--) - { - *--to= _dig_vec_lower[from & 15]; - from >>= 4; - } -} - -static void set_clock_seq_str() -{ - uint16 clock_seq= ((uint)(my_rnd(&uuid_rand)*16383)) | UUID_VARIANT; - tohex(clock_seq_and_node_str+1, clock_seq, 4); - nanoseq= 0; -} String *Item_func_uuid::val_str(String *str) { DBUG_ASSERT(fixed == 1); - char *s; - THD *thd= current_thd; + uchar guid[MY_UUID_SIZE]; - pthread_mutex_lock(&LOCK_uuid_generator); - if (! uuid_time) /* first UUID() call. initializing data */ - { - ulong tmp=sql_rnd_with_mutex(); - uchar mac[6]; - int i; - if (my_gethwaddr(mac)) - { - /* purecov: begin inspected */ - /* - generating random "hardware addr" - and because specs explicitly specify that it should NOT correlate - with a clock_seq value (initialized random below), we use a separate - randominit() here - */ - randominit(&uuid_rand, tmp + (ulong) thd, tmp + (ulong)global_query_id); - for (i=0; i < (int)sizeof(mac); i++) - mac[i]=(uchar)(my_rnd(&uuid_rand)*255); - /* purecov: end */ - } - s=clock_seq_and_node_str+sizeof(clock_seq_and_node_str)-1; - for (i=sizeof(mac)-1 ; i>=0 ; i--) - { - *--s=_dig_vec_lower[mac[i] & 15]; - *--s=_dig_vec_lower[mac[i] >> 4]; - } - randominit(&uuid_rand, tmp + (ulong) server_start_time, - tmp + (ulong) thd->status_var.bytes_sent); - set_clock_seq_str(); - } - - ulonglong tv= my_getsystime() + UUID_TIME_OFFSET + nanoseq; - - if (likely(tv > uuid_time)) - { - /* - Current time is ahead of last timestamp, as it should be. - If we "borrowed time", give it back, just as long as we - stay ahead of the previous timestamp. - */ - if (nanoseq) - { - DBUG_ASSERT((tv > uuid_time) && (nanoseq > 0)); - /* - -1 so we won't make tv= uuid_time for nanoseq >= (tv - uuid_time) - */ - ulong delta= min(nanoseq, (ulong) (tv - uuid_time -1)); - tv-= delta; - nanoseq-= delta; - } - } - else - { - if (unlikely(tv == uuid_time)) - { - /* - For low-res system clocks. If several requests for UUIDs - end up on the same tick, we add a nano-second to make them - different. - ( current_timestamp + nanoseq * calls_in_this_period ) - may end up > next_timestamp; this is OK. Nonetheless, we'll - try to unwind nanoseq when we get a chance to. - If nanoseq overflows, we'll start over with a new numberspace - (so the if() below is needed so we can avoid the ++tv and thus - match the follow-up if() if nanoseq overflows!). - */ - if (likely(++nanoseq)) - ++tv; - } - - if (unlikely(tv <= uuid_time)) - { - /* - If the admin changes the system clock (or due to Daylight - Saving Time), the system clock may be turned *back* so we - go through a period once more for which we already gave out - UUIDs. To avoid duplicate UUIDs despite potentially identical - times, we make a new random component. - We also come here if the nanoseq "borrowing" overflows. - In either case, we throw away any nanoseq borrowing since it's - irrelevant in the new numberspace. - */ - set_clock_seq_str(); - tv= my_getsystime() + UUID_TIME_OFFSET; - nanoseq= 0; - DBUG_PRINT("uuid",("making new numberspace")); - } - } - - uuid_time=tv; - pthread_mutex_unlock(&LOCK_uuid_generator); - - uint32 time_low= (uint32) (tv & 0xFFFFFFFF); - uint16 time_mid= (uint16) ((tv >> 32) & 0xFFFF); - uint16 time_hi_and_version= (uint16) ((tv >> 48) | UUID_VERSION); - - str->realloc(UUID_LENGTH+1); - str->length(UUID_LENGTH); + str->realloc(MY_UUID_STRING_LENGTH+1); + str->length(MY_UUID_STRING_LENGTH); str->set_charset(system_charset_info); - s=(char *) str->ptr(); - s[8]=s[13]='-'; - tohex(s, time_low, 8); - tohex(s+9, time_mid, 4); - tohex(s+14, time_hi_and_version, 4); - strmov(s+18, clock_seq_and_node_str); + my_uuid(guid); + my_uuid2str(guid, (char *)str->ptr()); + return str; } |