summaryrefslogtreecommitdiff
path: root/sql/set_var.cc
diff options
context:
space:
mode:
authorKristian Nielsen <knielsen@knielsen-hq.org>2017-03-20 11:55:24 +0100
committerKristian Nielsen <knielsen@knielsen-hq.org>2017-04-21 10:30:15 +0200
commit363d6a16ae3469496e9f17eab168c5b14fad7203 (patch)
tree3b6699d8baf03d77b0094f1387cf66da11a1eb1b /sql/set_var.cc
parent6a84473c28af10e072267bc811f280a49bdc8ca8 (diff)
downloadmariadb-git-363d6a16ae3469496e9f17eab168c5b14fad7203.tar.gz
MDEV-12179: Per-engine mysql.gtid_slave_pos table
Intermediate commit. Implement a --gtid-pos-auto-engines system variable. The variable is a list of engines for which mysql.gtid_slave_pos_ENGINE should be auto-created if needed. This commit only implements the option variable. It is not yet used to actually auto-create any tables, nor is there a corresponding command-line version of the option yet.
Diffstat (limited to 'sql/set_var.cc')
-rw-r--r--sql/set_var.cc174
1 files changed, 174 insertions, 0 deletions
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 07395e3e708..7b190f6244e 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -1278,3 +1278,177 @@ enum sys_var::where get_sys_var_value_origin(void *ptr)
return sys_var::CONFIG;
}
+
+/*
+ Find the next item in string of comma-separated items.
+ END_POS points at the end of the string.
+ ITEM_START and ITEM_END return the limits of the next item.
+ Returns true while items are available, false at the end.
+*/
+static bool
+engine_list_next_item(const char **pos, const char *end_pos,
+ const char **item_start, const char **item_end)
+{
+ if (*pos >= end_pos)
+ return false;
+ *item_start= *pos;
+ while (*pos < end_pos && **pos != ',')
+ ++*pos;
+ *item_end= *pos;
+ ++*pos;
+ return true;
+}
+
+
+static bool
+resolve_engine_list_item(plugin_ref *list, uint32 *idx,
+ const char *pos, const char *pos_end)
+{
+ LEX_STRING item_str;
+ plugin_ref ref;
+ uint32_t i;
+
+ item_str.str= const_cast<char*>(pos);
+ item_str.length= pos_end-pos;
+ ref= ha_resolve_by_name(NULL, &item_str, false);
+ if (!ref)
+ {
+ ErrConvString err(pos, pos_end-pos, system_charset_info);
+ my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), err.ptr());
+ return true;
+ }
+ /* Ignore duplicates, like --plugin-load does. */
+ for (i= 0; i < *idx; ++i)
+ {
+ if (plugin_hton(list[i]) == plugin_hton(ref))
+ {
+ plugin_unlock(NULL, ref);
+ return false;
+ }
+ }
+ list[*idx]= ref;
+ ++*idx;
+ return false;
+}
+
+
+/*
+ Helper for class Sys_var_pluginlist.
+ Resolve a comma-separated list of storage engine names to a null-terminated
+ array of plugin_ref.
+*/
+plugin_ref *
+resolve_engine_list(const char *str_arg, size_t str_arg_len)
+{
+ uint32 count, idx;
+ const char *pos, *item_start, *item_end;
+ const char *str_arg_end= str_arg + str_arg_len;
+ plugin_ref *res;
+
+ count= 0;
+ pos= str_arg;
+ for (;;)
+ {
+ if (!engine_list_next_item(&pos, str_arg_end, &item_start, &item_end))
+ break;
+ ++count;
+ }
+
+ res= (plugin_ref *)my_malloc((count+1)*sizeof(*res), MYF(MY_ZEROFILL|MY_WME));
+ if (!res)
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0), (int)((count+1)*sizeof(*res)));
+ goto err;
+ }
+
+ idx= 0;
+ pos= str_arg;
+ for (;;)
+ {
+ if (!engine_list_next_item(&pos, str_arg_end, &item_start, &item_end))
+ break;
+ DBUG_ASSERT(idx < count);
+ if (idx >= count)
+ break;
+ if (resolve_engine_list_item(res, &idx, item_start, item_end))
+ goto err;
+ }
+
+ return res;
+
+err:
+ free_engine_list(res);
+ return NULL;
+}
+
+
+void
+free_engine_list(plugin_ref *list)
+{
+ plugin_ref *p;
+
+ if (!list)
+ return;
+ for (p= list; *p; ++p)
+ plugin_unlock(NULL, *p);
+ my_free(list);
+}
+
+
+plugin_ref *
+copy_engine_list(plugin_ref *list)
+{
+ plugin_ref *p;
+ uint32 count, i;
+
+ for (p= list, count= 0; *p; ++p, ++count)
+ ;
+ p= (plugin_ref *)my_malloc((count+1)*sizeof(*p), MYF(0));
+ if (!p)
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0), (int)((count+1)*sizeof(*p)));
+ return NULL;
+ }
+ for (i= 0; i < count; ++i)
+ p[i]= my_plugin_lock(NULL, list[i]);
+ return p;
+}
+
+
+char *
+pretty_print_engine_list(THD *thd, plugin_ref *list)
+{
+ plugin_ref *p;
+ size_t size;
+ char *buf, *pos;
+
+ if (!list)
+ return thd->strmake("", 0);
+
+ size= 0;
+ for (p= list; *p; ++p)
+ size+= plugin_name(*p)->length + 1;
+ buf= static_cast<char *>(thd->alloc(size));
+ if (!buf)
+ return NULL;
+ pos= buf;
+ for (p= list; *p; ++p)
+ {
+ LEX_STRING *name;
+ size_t remain;
+
+ remain= buf + size - pos;
+ DBUG_ASSERT(remain > 0);
+ if (remain <= 1)
+ break;
+ if (pos != buf)
+ {
+ pos= strmake(pos, ",", remain-1);
+ --remain;
+ }
+ name= plugin_name(*p);
+ pos= strmake(pos, name->str, MY_MIN(name->length, remain-1));
+ }
+ *pos= '\0';
+ return buf;
+}