Skip to content

Commit

Permalink
Add support for string values
Browse files Browse the repository at this point in the history
The SET GLOBAL statement requires properly quoting of values. For example, the
following correct queries will fail if quotes are toggled:

mysql> SET GLOBAL innodb_lru_scan_depth = 2000;
mysql> SET GLOBAL master_info_repository = "TABLE";

`mysql_variable` module doesn't quote the value argument, therefore
string values will fail.

  # this task will pass, 2000 is passed without quotes
  - name: set a numeric value
    mysql_variable: variable=innodb_lru_scan_depth value=2000

  # this task will fail, TABLE is passed without quotes
  - name: set a string value
    mysql_variable: variable=master_info_repository value=TABLE

With this patch prepared statements are used. Proper quoting will be
done automatically based on the type of the variables thus an attempt
to convert to int, then to float is done in first place.

Booleans values, ie: ON, OFF, are not specially handled because they
can be quoted. For example, the following queries are correct and
equivalent, they all set _innodb_file_per_table_ to logical _True_:

mysql> SET GLOBAL innodb_file_per_table = "ON";
mysql> SET GLOBAL innodb_file_per_table = ON;
mysql> SET GLOBAL innodb_file_per_table = 1;

Tested in mysql 5.5 and 5.6.
  • Loading branch information
mmoya committed Feb 12, 2014
1 parent 8746671 commit 811aa26
Showing 1 changed file with 41 additions and 4 deletions.
45 changes: 41 additions & 4 deletions library/database/mysql_variables
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,48 @@ else:
mysqldb_found = True


def typedvalue(value):
"""
Convert value to number whenever possible, return same value
otherwise.
>>> typedvalue('3')
3
>>> typedvalue('3.0')
3.0
>>> typedvalue('foobar')
'foobar'
"""
try:
return int(value)
except ValueError:
pass

try:
return float(value)
except ValueError:
pass

return value


def getvariable(cursor, mysqlvar):
cursor.execute("SHOW VARIABLES LIKE '" + mysqlvar + "'")
mysqlvar_val = cursor.fetchall()
return mysqlvar_val


def setvariable(cursor, mysqlvar, value):
""" Set a global mysql variable to a given value
The DB driver will handle quoting of the given value based on its
type, thus numeric strings like '3.0' or '8' are illegal, they
should be passed as numeric literals.
"""
try:
cursor.execute("SET GLOBAL " + mysqlvar + "=" + value)
cursor.execute("SET GLOBAL " + mysqlvar + " = %s", (value,))
cursor.fetchall()
result = True
except Exception, e:
Expand Down Expand Up @@ -203,11 +237,14 @@ def main():
else:
if len(mysqlvar_val) < 1:
module.fail_json(msg="Variable not available", changed=False)
if value == mysqlvar_val[0][1]:
# Type values before using them
value_wanted = typedvalue(value)
value_actual = typedvalue(mysqlvar_val[0][1])
if value_wanted == value_actual:
module.exit_json(msg="Variable already set to requested value", changed=False)
result = setvariable(cursor, mysqlvar, value)
result = setvariable(cursor, mysqlvar, value_wanted)
if result is True:
module.exit_json(msg="Variable change succeeded", changed=True)
module.exit_json(msg="Variable change succeeded prev_value=%s" % value_actual, changed=True)
else:
module.fail_json(msg=result, changed=False)

Expand Down

0 comments on commit 811aa26

Please sign in to comment.