summaryrefslogtreecommitdiff
path: root/sql/set_var.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/set_var.cc')
-rw-r--r--sql/set_var.cc185
1 files changed, 185 insertions, 0 deletions
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 03378f2be73..f8287ca1ffe 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -35,6 +35,7 @@
#include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone
#include "sql_acl.h" // SUPER_ACL
#include "sql_select.h" // free_underlaid_joins
+#include "sql_show.h"
#include "sql_view.h" // updatable_views_with_limit_typelib
#include "lock.h" // lock_global_read_lock,
// make_global_read_lock_block_commit,
@@ -240,6 +241,7 @@ bool sys_var::check(THD *thd, set_var *var)
uchar *sys_var::value_ptr(THD *thd, enum_var_type type, const LEX_STRING *base)
{
+ DBUG_ASSERT(base);
if (type == OPT_GLOBAL || scope() == GLOBAL)
{
mysql_mutex_assert_owner(&LOCK_global_system_variables);
@@ -468,6 +470,7 @@ CHARSET_INFO *sys_var::charset(THD *thd)
system_charset_info;
}
+
typedef struct old_names_map_st
{
const char *old_name;
@@ -938,3 +941,185 @@ int set_var_collation_client::update(THD *thd)
return 0;
}
+/*****************************************************************************
+ INFORMATION_SCHEMA.SYSTEM_VARIABLES
+*****************************************************************************/
+static void store_value_ptr(Field *field, sys_var *var, String *str,
+ uchar *value_ptr)
+{
+ field->set_notnull();
+ str= var->val_str_nolock(str, field->table->in_use, value_ptr);
+ if (str)
+ field->store(str->ptr(), str->length(), str->charset());
+}
+
+static void store_var(Field *field, sys_var *var, enum_var_type scope,
+ String *str)
+{
+ if (var->check_type(scope))
+ return;
+
+ store_value_ptr(field, var, str,
+ var->value_ptr(field->table->in_use, scope, &null_lex_str));
+}
+
+
+int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ char name_buffer[NAME_CHAR_LEN];
+ enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
+ bool res= 1;
+ CHARSET_INFO *scs= system_charset_info;
+ StringBuffer<STRING_BUFFER_USUAL_SIZE> strbuf(scs);
+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : 0;
+ Field **fields=tables->table->field;
+
+ DBUG_ASSERT(tables->table->in_use == thd);
+
+ cond= make_cond_for_info_schema(cond, tables);
+ thd->count_cuted_fields= CHECK_FIELD_WARN;
+ mysql_rwlock_rdlock(&LOCK_system_variables_hash);
+
+ for (uint i= 0; i < system_variable_hash.records; i++)
+ {
+ sys_var *var= (sys_var*) my_hash_element(&system_variable_hash, i);
+
+ strmake_buf(name_buffer, var->name.str);
+ my_caseup_str(system_charset_info, name_buffer);
+
+ /* this must be done before evaluating cond */
+ restore_record(tables->table, s->default_values);
+ fields[0]->store(name_buffer, strlen(name_buffer), scs);
+
+ if ((wild && wild_case_compare(system_charset_info, name_buffer, wild))
+ || (cond && !cond->val_int()))
+ continue;
+
+ mysql_mutex_lock(&LOCK_global_system_variables);
+
+ // SESSION_VALUE
+ store_var(fields[1], var, OPT_SESSION, &strbuf);
+
+ // GLOBAL_VALUE
+ store_var(fields[2], var, OPT_GLOBAL, &strbuf);
+
+ // DEFAULT_VALUE
+ uchar *def= var->is_readonly() && var->option.id < 0
+ ? 0 : var->default_value_ptr(thd);
+ if (def)
+ store_value_ptr(fields[3], var, &strbuf, def);
+
+ mysql_mutex_unlock(&LOCK_global_system_variables);
+
+ static const LEX_CSTRING scopes[]=
+ {
+ { STRING_WITH_LEN("GLOBAL") },
+ { STRING_WITH_LEN("SESSION") },
+ { STRING_WITH_LEN("SESSION ONLY") }
+ };
+ const LEX_CSTRING *scope= scopes + var->scope();
+ fields[4]->store(scope->str, scope->length, scs);
+
+#if SIZEOF_LONG == SIZEOF_INT
+#define LONG_TYPE "INT"
+#else
+#define LONG_TYPE "BIGINT"
+#endif
+
+ static const LEX_CSTRING types[]=
+ {
+ { 0, 0 }, // unused 0
+ { 0, 0 }, // GET_NO_ARG 1
+ { STRING_WITH_LEN("BOOLEAN") }, // GET_BOOL 2
+ { STRING_WITH_LEN("INT") }, // GET_INT 3
+ { STRING_WITH_LEN("INT UNSIGNED") }, // GET_UINT 4
+ { STRING_WITH_LEN(LONG_TYPE) }, // GET_LONG 5
+ { STRING_WITH_LEN(LONG_TYPE " UNSIGNED") }, // GET_ULONG 6
+ { STRING_WITH_LEN("BIGINT") }, // GET_LL 7
+ { STRING_WITH_LEN("BIGINT UNSIGNED") }, // GET_ULL 8
+ { STRING_WITH_LEN("VARCHAR") }, // GET_STR 9
+ { STRING_WITH_LEN("VARCHAR") }, // GET_STR_ALLOC 10
+ { 0, 0 }, // GET_DISABLED 11
+ { STRING_WITH_LEN("ENUM") }, // GET_ENUM 12
+ { STRING_WITH_LEN("SET") }, // GET_SET 13
+ { STRING_WITH_LEN("DOUBLE") }, // GET_DOUBLE 14
+ { STRING_WITH_LEN("FLAGSET") }, // GET_FLAGSET 15
+ };
+ const LEX_CSTRING *type= types + (var->option.var_type & GET_TYPE_MASK);
+ fields[5]->store(type->str, type->length, scs);
+
+ fields[6]->store(var->option.comment, strlen(var->option.comment),
+ scs);
+
+ bool is_unsigned= true;
+ switch (var->option.var_type)
+ {
+ case GET_INT:
+ case GET_LONG:
+ case GET_LL:
+ is_unsigned= false;
+ /* fall through */
+ case GET_UINT:
+ case GET_ULONG:
+ case GET_ULL:
+ fields[7]->set_notnull();
+ fields[8]->set_notnull();
+ fields[9]->set_notnull();
+ fields[7]->store(var->option.min_value, is_unsigned);
+ fields[8]->store(var->option.max_value, is_unsigned);
+ fields[9]->store(var->option.block_size, is_unsigned);
+ break;
+ case GET_DOUBLE:
+ fields[7]->set_notnull();
+ fields[8]->set_notnull();
+ fields[7]->store(getopt_ulonglong2double(var->option.min_value));
+ fields[8]->store(getopt_ulonglong2double(var->option.max_value));
+ }
+
+ TYPELIB *tl= var->option.typelib;
+ if (tl)
+ {
+ uint i;
+ strbuf.length(0);
+ for (i=0; i + 1 < tl->count; i++)
+ {
+ strbuf.append(tl->type_names[i]);
+ strbuf.append(',');
+ }
+ strbuf.append(tl->type_names[i]);
+ fields[10]->set_notnull();
+ fields[10]->store(strbuf.ptr(), strbuf.length(), scs);
+ }
+
+ static const LEX_CSTRING yesno[]=
+ {
+ { STRING_WITH_LEN("NO") },
+ { STRING_WITH_LEN("YES") }
+ };
+ const LEX_CSTRING *yn = yesno + var->is_readonly();
+ fields[11]->store(yn->str, yn->length, scs);
+
+ if (var->option.id >= 0)
+ {
+ static const LEX_CSTRING args[]=
+ {
+ { STRING_WITH_LEN("NONE") }, // NO_ARG
+ { STRING_WITH_LEN("OPTIONAL") }, // OPT_ARG
+ { STRING_WITH_LEN("REQUIRED") } // REQUIRED_ARG
+ };
+ const LEX_CSTRING *arg= args + var->option.arg_type;
+ fields[12]->set_notnull();
+ fields[12]->store(arg->str, arg->length, scs);
+ }
+
+ if (schema_table_store_record(thd, tables->table))
+ goto end;
+ thd->get_stmt_da()->inc_current_row_for_warning();
+ }
+ res= 0;
+end:
+ mysql_rwlock_unlock(&LOCK_system_variables_hash);
+ thd->count_cuted_fields= save_count_cuted_fields;
+ return res;
+}
+