diff options
Diffstat (limited to 'sql/item_strfunc.cc')
-rw-r--r-- | sql/item_strfunc.cc | 372 |
1 files changed, 146 insertions, 226 deletions
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 68d49b90475..0635556be40 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -43,7 +43,6 @@ #include "set_var.h" #include "sql_base.h" #include "sql_time.h" -#include "sql_acl.h" // SUPER_ACL #include "des_key_file.h" // st_des_keyschedule, st_des_keyblock #include "password.h" // my_make_scrambled_password, // my_make_scrambled_password_323 @@ -58,25 +57,21 @@ C_MODE_END size_t username_char_length= 80; +/* + Calculate max length of string from length argument to LEFT and RIGHT +*/ -class Repeat_count +static uint32 max_length_for_string(Item *item) { - ulonglong m_count; -public: - Repeat_count(Item *item) - :m_count(0) + ulonglong length= item->val_int(); + /* Note that if value is NULL, val_int() returned 0 */ + if (length > (ulonglong) INT_MAX32) { - Longlong_hybrid nr= item->to_longlong_hybrid(); - if (!item->null_value && !nr.neg()) - { - // Assume that the maximum length of a String is < INT_MAX32 - m_count= (ulonglong) nr.value(); - if (m_count > (ulonglong) INT_MAX32) - m_count= (ulonglong) INT_MAX32; - } + /* Limit string length to maxium string length in MariaDB (2G) */ + length= item->unsigned_flag ? (ulonglong) INT_MAX32 : 0; } - ulonglong count() const { return m_count; } -}; + return (uint32) length; +} /* @@ -844,7 +839,7 @@ String *Item_func_des_decrypt::val_str(String *str) { uint key_number=(uint) (*res)[0] & 127; // Check if automatic key and that we have privilege to uncompress using it - if (!(current_thd->security_ctx->master_access & SUPER_ACL) || + if (!(current_thd->security_ctx->master_access & PRIV_DES_DECRYPT_ONE_ARG) || key_number > 9) goto error; @@ -1105,7 +1100,7 @@ String *Item_func_reverse::val_str(String *str) end= res->end(); tmp= (char *) str->end(); #ifdef USE_MB - if (use_mb(res->charset())) + if (res->use_mb()) { uint32 l; while (ptr < end) @@ -1178,7 +1173,7 @@ String *Item_func_replace::val_str_internal(String *str, res->set_charset(collation.collation); #ifdef USE_MB - binary_cmp = ((res->charset()->state & MY_CS_BINSORT) || !use_mb(res->charset())); + binary_cmp = ((res->charset()->state & MY_CS_BINSORT) || !res->use_mb()); #endif if (res2->length() == 0) @@ -1293,10 +1288,10 @@ null: bool Item_func_replace::fix_length_and_dec() { ulonglong char_length= (ulonglong) args[0]->max_char_length(); - int diff=(int) (args[2]->max_char_length() - args[1]->max_char_length()); - if (diff > 0 && args[1]->max_char_length()) + int diff=(int) (args[2]->max_char_length() - 1); + if (diff > 0) { // Calculate of maxreplaces - ulonglong max_substrs= char_length / args[1]->max_char_length(); + ulonglong max_substrs= char_length; char_length+= max_substrs * (uint) diff; } @@ -1308,13 +1303,6 @@ bool Item_func_replace::fix_length_and_dec() /*********************************************************************/ -bool Item_func_regexp_replace::fix_fields(THD *thd, Item **ref) -{ - re.set_recursion_limit(thd); - return Item_str_func::fix_fields(thd, ref); -} - - bool Item_func_regexp_replace::fix_length_and_dec() { if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 3)) @@ -1344,8 +1332,8 @@ bool Item_func_regexp_replace::append_replacement(String *str, my_wc_t wc; int cnv, n; - if ((cnv= cs->cset->mb_wc(cs, &wc, (const uchar *) beg, - (const uchar *) end)) < 1) + if ((cnv= cs->mb_wc(&wc, (const uchar *) beg, + (const uchar *) end)) < 1) break; /* End of line */ beg+= cnv; @@ -1356,8 +1344,8 @@ bool Item_func_regexp_replace::append_replacement(String *str, continue; } - if ((cnv= cs->cset->mb_wc(cs, &wc, (const uchar *) beg, - (const uchar *) end)) < 1) + if ((cnv= cs->mb_wc(&wc, (const uchar *) beg, + (const uchar *) end)) < 1) break; /* End of line */ beg+= cnv; @@ -1366,7 +1354,7 @@ bool Item_func_regexp_replace::append_replacement(String *str, if (n < re.nsubpatterns()) { /* A valid sub-pattern reference found */ - int pbeg= re.subpattern_start(n), plength= re.subpattern_end(n) - pbeg; + size_t pbeg= re.subpattern_start(n), plength= re.subpattern_end(n) - pbeg; if (str->append(source->str + pbeg, plength, cs)) return true; } @@ -1395,7 +1383,7 @@ String *Item_func_regexp_replace::val_str(String *str) String *source= args[0]->val_str(&tmp0); String *replace= args[2]->val_str(&tmp2); LEX_CSTRING src, rpl; - int startoffset= 0; + size_t startoffset= 0; if ((null_value= (args[0]->null_value || args[2]->null_value || re.recompile(args[1])))) @@ -1405,8 +1393,8 @@ String *Item_func_regexp_replace::val_str(String *str) !(replace= re.convert_if_needed(replace, &re.replace_converter))) goto err; - src= source->lex_cstring(); - rpl= replace->lex_cstring(); + source->get_value(&src); + replace->get_value(&rpl); str->length(0); str->set_charset(collation.collation); @@ -1424,7 +1412,8 @@ String *Item_func_regexp_replace::val_str(String *str) Append the rest of the source string starting from startoffset until the end of the source. */ - if (str->append(src.str + startoffset, src.length - startoffset, re.library_charset())) + if (str->append(src.str + startoffset, src.length - startoffset, + re.library_charset())) goto err; return str; } @@ -1433,7 +1422,8 @@ String *Item_func_regexp_replace::val_str(String *str) Append prefix, the part before the matching pattern. starting from startoffset until the next match */ - if (str->append(src.str + startoffset, re.subpattern_start(0) - startoffset, re.library_charset())) + if (str->append(src.str + startoffset, + re.subpattern_start(0) - startoffset, re.library_charset())) goto err; // Append replacement @@ -1451,13 +1441,6 @@ err: } -bool Item_func_regexp_substr::fix_fields(THD *thd, Item **ref) -{ - re.set_recursion_limit(thd); - return Item_str_func::fix_fields(thd, ref); -} - - bool Item_func_regexp_substr::fix_length_and_dec() { if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 2)) @@ -1492,8 +1475,7 @@ String *Item_func_regexp_substr::val_str(String *str) return str; if (str->append(source->ptr() + re.subpattern_start(0), - re.subpattern_end(0) - re.subpattern_start(0), - re.library_charset())) + re.subpattern_length(0), re.library_charset())) goto err; return str; @@ -1659,8 +1641,8 @@ void Item_str_func::left_right_max_length() uint32 char_length= args[0]->max_char_length(); if (args[1]->const_item() && !args[1]->is_expensive()) { - Repeat_count tmp(args[1]); - set_if_smaller(char_length, (uint) tmp.count()); + uint32 length= max_length_for_string(args[1]); + set_if_smaller(char_length, length); } fix_char_length(char_length); } @@ -1821,7 +1803,7 @@ String *Item_func_substr_index::val_str(String *str) res->set_charset(collation.collation); #ifdef USE_MB - if (use_mb(res->charset())) + if (res->use_mb()) { const char *ptr= res->ptr(); const char *strend= ptr+res->length(); @@ -2026,7 +2008,7 @@ String *Item_func_rtrim::val_str(String *str) { char chr=(*remove_str)[0]; #ifdef USE_MB - if (use_mb(collation.collation)) + if (collation.collation->use_mb()) { while (ptr < end) { @@ -2043,7 +2025,7 @@ String *Item_func_rtrim::val_str(String *str) { const char *r_ptr=remove_str->ptr(); #ifdef USE_MB - if (use_mb(collation.collation)) + if (collation.collation->use_mb()) { loop: while (ptr + remove_length < end) @@ -2102,7 +2084,7 @@ String *Item_func_trim::val_str(String *str) while (ptr+remove_length <= end && !memcmp(ptr,r_ptr,remove_length)) ptr+=remove_length; #ifdef USE_MB - if (use_mb(collation.collation)) + if (collation.collation->use_mb()) { char *p=ptr; uint32 l; @@ -2575,10 +2557,10 @@ String *Item_func_soundex::val_str(String *str) for ( ; ; ) /* Skip pre-space */ { - if ((rc= cs->cset->mb_wc(cs, &wc, (uchar*) from, (uchar*) end)) <= 0) + if ((rc= cs->mb_wc(&wc, (uchar*) from, (uchar*) end)) <= 0) return make_empty_result(str); /* EOL or invalid byte sequence */ - - if (rc == 1 && cs->ctype) + + if (rc == 1 && cs->m_ctype) { /* Single byte letter found */ if (my_isalpha(cs, *from)) @@ -2597,7 +2579,7 @@ String *Item_func_soundex::val_str(String *str) /* Multibyte letter found */ wc= soundex_toupper(wc); last_ch= get_scode(wc); // Code of the first letter - if ((rc= cs->cset->wc_mb(cs, wc, (uchar*) to, (uchar*) to_end)) <= 0) + if ((rc= cs->wc_mb(wc, (uchar*) to, (uchar*) to_end)) <= 0) { /* Extra safety - should not really happen */ DBUG_ASSERT(false); @@ -2615,10 +2597,10 @@ String *Item_func_soundex::val_str(String *str) */ for (nchars= 1 ; ; ) { - if ((rc= cs->cset->mb_wc(cs, &wc, (uchar*) from, (uchar*) end)) <= 0) + if ((rc= cs->mb_wc(&wc, (uchar*) from, (uchar*) end)) <= 0) break; /* EOL or invalid byte sequence */ - if (rc == 1 && cs->ctype) + if (rc == 1 && cs->m_ctype) { if (!my_isalpha(cs, *from++)) continue; @@ -2634,8 +2616,7 @@ String *Item_func_soundex::val_str(String *str) if ((ch != '0') && (ch != last_ch)) // if not skipped or double { // letter, copy to output - if ((rc= cs->cset->wc_mb(cs, (my_wc_t) ch, - (uchar*) to, (uchar*) to_end)) <= 0) + if ((rc= cs->wc_mb((my_wc_t) ch, (uchar*) to, (uchar*) to_end)) <= 0) { // Extra safety - should not really happen DBUG_ASSERT(false); @@ -2651,7 +2632,7 @@ String *Item_func_soundex::val_str(String *str) if (nchars < 4) { uint nbytes= (4 - nchars) * cs->mbminlen; - cs->cset->fill(cs, to, nbytes, '0'); + cs->fill(to, nbytes, '0'); to+= nbytes; } @@ -3053,8 +3034,8 @@ bool Item_func_repeat::fix_length_and_dec() DBUG_ASSERT(collation.collation != NULL); if (args[1]->const_item() && !args[1]->is_expensive()) { - Repeat_count tmp(args[1]); - ulonglong char_length= (ulonglong) args[0]->max_char_length() * tmp.count(); + uint32 length= max_length_for_string(args[1]); + ulonglong char_length= (ulonglong) args[0]->max_char_length() * length; fix_char_length_ulonglong(char_length); return false; } @@ -3127,7 +3108,7 @@ bool Item_func_space::fix_length_and_dec() collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); if (args[0]->const_item() && !args[0]->is_expensive()) { - fix_char_length_ulonglong(Repeat_count(args[0]).count()); + fix_char_length_ulonglong(max_length_for_string(args[0])); return false; } max_length= MAX_BLOB_WIDTH; @@ -3173,7 +3154,7 @@ String *Item_func_space::val_str(String *str) goto err; str->length(tot_length); str->set_charset(cs); - cs->cset->fill(cs, (char*) str->ptr(), tot_length, ' '); + cs->fill((char*) str->ptr(), tot_length, ' '); return str; err: @@ -3252,7 +3233,7 @@ bool Item_func_pad::fix_length_and_dec() DBUG_ASSERT(collation.collation->mbmaxlen > 0); if (args[1]->const_item() && !args[1]->is_expensive()) { - fix_char_length_ulonglong(Repeat_count(args[1]).count()); + fix_char_length_ulonglong(max_length_for_string(args[1])); return false; } max_length= MAX_BLOB_WIDTH; @@ -3514,11 +3495,11 @@ String *Item_func_conv::val_str(String *str) else { if (from_base < 0) - dec= my_strntoll(res->charset(), res->ptr(), res->length(), - -from_base, &endptr, &err); + dec= res->charset()->strntoll(res->ptr(), res->length(), + -from_base, &endptr, &err); else - dec= (longlong) my_strntoull(res->charset(), res->ptr(), res->length(), - from_base, &endptr, &err); + dec= (longlong) res->charset()->strntoull(res->ptr(), res->length(), + from_base, &endptr, &err); } if (!(ptr= longlong2str(dec, ans, to_base)) || @@ -3573,10 +3554,12 @@ String *Item_func_set_collation::val_str(String *str) bool Item_func_set_collation::fix_length_and_dec() { - if (!my_charset_same(args[0]->collation.collation, m_set_collation)) + if (agg_arg_charsets_for_string_result(collation, args, 1)) + return true; + if (!my_charset_same(collation.collation, m_set_collation)) { my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), - m_set_collation->name, args[0]->collation.collation->csname); + m_set_collation->name, collation.collation->csname); return TRUE; } collation.set(m_set_collation, DERIVATION_EXPLICIT, @@ -3640,7 +3623,7 @@ bool Item_func_weight_string::fix_length_and_dec() size_t char_length; char_length= ((cs->state & MY_CS_STRNXFRM_BAD_NWEIGHTS) || !nweights) ? args[0]->max_char_length() : nweights * cs->levels_for_order; - max_length= (uint32)cs->coll->strnxfrmlen(cs, char_length * cs->mbmaxlen); + max_length= (uint32) cs->strnxfrmlen(char_length * cs->mbmaxlen); } maybe_null= 1; return FALSE; @@ -3691,7 +3674,7 @@ String *Item_func_weight_string::val_str(String *str) char_length= (flags & MY_STRXFRM_PAD_WITH_SPACE) ? res->numchars() : (res->length() / cs->mbminlen); } - tmp_length= cs->coll->strnxfrmlen(cs, char_length * cs->mbmaxlen); + tmp_length= cs->strnxfrmlen(char_length * cs->mbmaxlen); } { @@ -3710,11 +3693,10 @@ String *Item_func_weight_string::val_str(String *str) if (str->alloc(tmp_length)) goto nl; - frm_length= cs->coll->strnxfrm(cs, - (uchar *) str->ptr(), tmp_length, - nweights ? nweights : (uint)tmp_length, - (const uchar *) res->ptr(), res->length(), - flags); + frm_length= cs->strnxfrm((char*) str->ptr(), tmp_length, + nweights ? nweights : (uint) tmp_length, + res->ptr(), res->length(), + flags); DBUG_ASSERT(frm_length <= tmp_length); str->length(frm_length); @@ -3833,10 +3815,10 @@ String *Item_func_like_range::val_str(String *str) goto err; null_value=0; - if (cs->coll->like_range(cs, res->ptr(), res->length(), - '\\', '_', '%', (size_t)nbytes, - (char*) min_str.ptr(), (char*) max_str.ptr(), - &min_len, &max_len)) + if (cs->like_range(res->ptr(), res->length(), + '\\', '_', '%', (size_t)nbytes, + (char*) min_str.ptr(), (char*) max_str.ptr(), + &min_len, &max_len)) goto err; min_str.set_charset(collation.collation); @@ -4105,7 +4087,7 @@ String *Item_func_quote::val_str(String *str) to_end= (uchar*) to + new_length; /* Put leading quote */ - if ((mblen= cs->cset->wc_mb(cs, '\'', (uchar *) to, to_end)) <= 0) + if ((mblen= cs->wc_mb('\'', (uchar *) to, to_end)) <= 0) goto toolong; to+= mblen; @@ -4113,7 +4095,7 @@ String *Item_func_quote::val_str(String *str) { my_wc_t wc; bool escape; - if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) start, (uchar*) end)) <= 0) + if ((mblen= cs->mb_wc(&wc, (uchar*) start, (uchar*) end)) <= 0) goto null; start+= mblen; switch (wc) { @@ -4125,17 +4107,17 @@ String *Item_func_quote::val_str(String *str) } if (escape) { - if ((mblen= cs->cset->wc_mb(cs, '\\', (uchar*) to, to_end)) <= 0) + if ((mblen= cs->wc_mb('\\', (uchar*) to, to_end)) <= 0) goto toolong; to+= mblen; } - if ((mblen= cs->cset->wc_mb(cs, wc, (uchar*) to, to_end)) <= 0) + if ((mblen= cs->wc_mb(wc, (uchar*) to, to_end)) <= 0) goto toolong; to+= mblen; } /* Put trailing quote */ - if ((mblen= cs->cset->wc_mb(cs, '\'', (uchar *) to, to_end)) <= 0) + if ((mblen= cs->wc_mb('\'', (uchar *) to, to_end)) <= 0) goto toolong; to+= mblen; new_length= (uint)(to - str->ptr()); @@ -4448,24 +4430,7 @@ bool Item_func_dyncol_create::prepare_arguments(THD *thd, bool force_names_arg) uint valpos= i * 2 + 1; DYNAMIC_COLUMN_TYPE type= defs[i].type; if (type == DYN_COL_NULL) - switch (args[valpos]->field_type()) - { - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_SET: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_GEOMETRY: - type= DYN_COL_STRING; - break; - default: - break; - } - + type= args[valpos]->type_handler()->dyncol_type(args[valpos]); if (type == DYN_COL_STRING && args[valpos]->type() == Item::FUNC_ITEM && ((Item_func *)args[valpos])->functype() == DYNCOL_FUNC) @@ -4482,63 +4447,7 @@ bool Item_func_dyncol_create::prepare_arguments(THD *thd, bool force_names_arg) uint valpos= i * 2 + 1; DYNAMIC_COLUMN_TYPE type= defs[i].type; if (type == DYN_COL_NULL) // auto detect - { - /* - We don't have a default here to ensure we get a warning if - one adds a new not handled MYSQL_TYPE_... - */ - switch (args[valpos]->field_type()) { - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: - type= DYN_COL_DECIMAL; - break; - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_LONGLONG: - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_YEAR: - case MYSQL_TYPE_BIT: - type= args[valpos]->unsigned_flag ? DYN_COL_UINT : DYN_COL_INT; - break; - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - type= DYN_COL_DOUBLE; - break; - case MYSQL_TYPE_NULL: - type= DYN_COL_NULL; - break; - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_TIMESTAMP2: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_DATETIME2: - type= DYN_COL_DATETIME; - break; - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_NEWDATE: - type= DYN_COL_DATE; - break; - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_TIME2: - type= DYN_COL_TIME; - break; - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_SET: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_VAR_STRING: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_GEOMETRY: - type= DYN_COL_STRING; - break; - case MYSQL_TYPE_VARCHAR_COMPRESSED: - case MYSQL_TYPE_BLOB_COMPRESSED: - DBUG_ASSERT(0); - } - } + type= args[valpos]->type_handler()->dyncol_type(args[valpos]); if (type == DYN_COL_STRING && args[valpos]->type() == Item::FUNC_ITEM && ((Item_func *)args[valpos])->functype() == DYNCOL_FUNC) @@ -5116,8 +5025,8 @@ double Item_dyncol_get::val_real() { int error; char *end; - double res= my_strntod(val.x.string.charset, (char*) val.x.string.value.str, - val.x.string.value.length, &end, &error); + double res= val.x.string.charset->strntod((char*) val.x.string.value.str, + val.x.string.value.length, &end, &error); if (end != (char*) val.x.string.value.str + val.x.string.value.length || error) @@ -5361,28 +5270,33 @@ String *Item_temptable_rowid::val_str(String *str) str_value.set((char*)(table->file->ref), max_length, &my_charset_bin); return &str_value; } + #ifdef WITH_WSREP #include "wsrep_mysqld.h" +/* Format is %d-%d-%llu */ +#define WSREP_MAX_WSREP_SERVER_GTID_STR_LEN 10+1+10+1+20 String *Item_func_wsrep_last_written_gtid::val_str_ascii(String *str) { - wsrep::gtid gtid= current_thd->wsrep_cs().last_written_gtid(); - if (gtid_str.alloc(wsrep::gtid_c_str_len())) + if (gtid_str.alloc(WSREP_MAX_WSREP_SERVER_GTID_STR_LEN+1)) { - my_error(ER_OUTOFMEMORY, wsrep::gtid_c_str_len()); - null_value= true; - return NULL; + my_error(ER_OUTOFMEMORY, WSREP_MAX_WSREP_SERVER_GTID_STR_LEN); + null_value= TRUE; + return 0; } - ssize_t gtid_len= gtid_print_to_c_str(gtid, (char*) gtid_str.ptr(), - wsrep::gtid_c_str_len()); + ssize_t gtid_len= my_snprintf((char*)gtid_str.ptr(), + WSREP_MAX_WSREP_SERVER_GTID_STR_LEN+1, + "%u-%u-%llu", wsrep_gtid_server.domain_id, + wsrep_gtid_server.server_id, + current_thd->wsrep_last_written_gtid_seqno); if (gtid_len < 0) { my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0), func_name(), - "wsrep_gtid_print failed"); - null_value= true; - return NULL; + "wsrep_gtid_print failed"); + null_value= TRUE; + return 0; } gtid_str.length(gtid_len); return >id_str; @@ -5390,27 +5304,23 @@ String *Item_func_wsrep_last_written_gtid::val_str_ascii(String *str) String *Item_func_wsrep_last_seen_gtid::val_str_ascii(String *str) { - wsrep::gtid gtid= wsrep::gtid::undefined(); - if (Wsrep_server_state::instance().is_provider_loaded()) - { - /* TODO: Should call Wsrep_server_state.instance().last_committed_gtid() - instead. */ - gtid= Wsrep_server_state::instance().provider().last_committed_gtid(); - } - if (gtid_str.alloc(wsrep::gtid_c_str_len())) + if (gtid_str.alloc(WSREP_MAX_WSREP_SERVER_GTID_STR_LEN+1)) { - my_error(ER_OUTOFMEMORY, wsrep::gtid_c_str_len()); - null_value= true; - return NULL; + my_error(ER_OUTOFMEMORY, WSREP_MAX_WSREP_SERVER_GTID_STR_LEN); + null_value= TRUE; + return 0; } - ssize_t gtid_len= wsrep::gtid_print_to_c_str(gtid, (char*) gtid_str.ptr(), - wsrep::gtid_c_str_len()); + ssize_t gtid_len= my_snprintf((char*)gtid_str.ptr(), + WSREP_MAX_WSREP_SERVER_GTID_STR_LEN+1, + "%u-%u-%llu", wsrep_gtid_server.domain_id, + wsrep_gtid_server.server_id, + wsrep_gtid_server.seqno()); if (gtid_len < 0) { my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0), func_name(), "wsrep_gtid_print failed"); - null_value= true; - return NULL; + null_value= TRUE; + return 0; } gtid_str.length(gtid_len); return >id_str; @@ -5418,49 +5328,59 @@ String *Item_func_wsrep_last_seen_gtid::val_str_ascii(String *str) longlong Item_func_wsrep_sync_wait_upto::val_int() { - int timeout= -1; - String* gtid_str= args[0]->val_str(&value); - if (gtid_str == NULL) - { - my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); - return 0LL; - } - - if (arg_count == 2) - { - timeout= args[1]->val_int(); - } + String *gtid_str __attribute__((unused)) = args[0]->val_str(&value); + null_value=0; + uint timeout; + rpl_gtid *gtid_list; + uint32 count; + int wait_gtid_ret= 0; + int ret= 1; - wsrep_gtid_t gtid; - int gtid_len= wsrep_gtid_scan(gtid_str->ptr(), gtid_str->length(), >id); - if (gtid_len < 0) + if (args[0]->null_value) { my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); - return 0LL; + null_value= TRUE; + return 0; } - if (gtid.seqno == WSREP_SEQNO_UNDEFINED && - wsrep_uuid_compare(>id.uuid, &WSREP_UUID_UNDEFINED) == 0) + if (arg_count==2 && !args[1]->null_value) + timeout= (uint)(args[1]->val_real()); + else + timeout= (uint)-1; + + if (!(gtid_list= gtid_parse_string_to_list(gtid_str->ptr(), gtid_str->length(), + &count))) { - return 1LL; + my_error(ER_INCORRECT_GTID_STATE, MYF(0), func_name()); + null_value= TRUE; + return 0; } - - enum wsrep::provider::status status= - wsrep_sync_wait_upto(current_thd, >id, timeout); - - if (status) + if (count == 1) { - int err; - switch (status) { - case wsrep::provider::error_transaction_missing: - err= ER_WRONG_ARGUMENTS; - break; - default: - err= ER_LOCK_WAIT_TIMEOUT; + if (wsrep_check_gtid_seqno(gtid_list[0].domain_id, gtid_list[0].server_id, + gtid_list[0].seq_no)) + { + wait_gtid_ret= wsrep_gtid_server.wait_gtid_upto(gtid_list[0].seq_no, timeout); + if ((wait_gtid_ret == ETIMEDOUT) || (wait_gtid_ret == ETIME)) + { + my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0), func_name()); + ret= 0; + } + else if (wait_gtid_ret == ENOMEM) + { + my_error(ER_OUTOFMEMORY, MYF(0), func_name()); + ret= 0; + } } - my_error(err, MYF(0), func_name()); - return 0LL; } - return 1LL; + else + { + my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); + null_value= TRUE; + ret= 0; + } + my_free(gtid_list); + return ret; } + #endif /* WITH_WSREP */ |