From aebbcd6955a212158f3313b3caa0170a93d9d268 Mon Sep 17 00:00:00 2001 From: Jonathan Mainguy Date: Tue, 5 Jan 2016 19:57:01 -0500 Subject: [PATCH] add ansi support --- database/mysql/mysql_user.py | 40 ++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/database/mysql/mysql_user.py b/database/mysql/mysql_user.py index 3ca952ca08e..d53accdd19f 100644 --- a/database/mysql/mysql_user.py +++ b/database/mysql/mysql_user.py @@ -191,6 +191,16 @@ def server_version_check(cursor): else: return False +def get_mode(cursor): + cursor.execute('SELECT @@GLOBAL.sql_mode') + result = cursor.fetchone() + mode_str = result[0] + if 'ANSI' in mode_str: + mode = 'ANSI' + else: + mode = 'NOTANSI' + return mode + def user_exists(cursor, user, host, host_all): if host_all: cursor.execute("SELECT count(*) FROM user WHERE user = %s", user) @@ -357,7 +367,7 @@ def privileges_get(cursor, user,host): output[db] = privileges return output -def privileges_unpack(priv): +def privileges_unpack(priv, mode): """ Take a privileges string, typically passed as a parameter, and unserialize it into a dictionary, the same format as privileges_get() above. We have this custom format to avoid using YAML/JSON strings inside YAML playbooks. Example @@ -368,6 +378,10 @@ def privileges_unpack(priv): The privilege USAGE stands for no privileges, so we add that in on *.* if it's not specified in the string, as MySQL will always provide this by default. """ + if mode == 'ANSI': + quote = '"' + else: + quote = '`' output = {} privs = [] for item in priv.strip().split('/'): @@ -375,7 +389,7 @@ def privileges_unpack(priv): dbpriv = pieces[0].rsplit(".", 1) # Do not escape if privilege is for database '*' (all databases) if dbpriv[0].strip('`') != '*': - pieces[0] = "`%s`.%s" % (dbpriv[0].strip('`'), dbpriv[1]) + pieces[0] = '%s%s%s.%s' % (quote, dbpriv[0].strip('`'), quote, dbpriv[1]) if '(' in pieces[1]: output[pieces[0]] = re.split(r',\s*(?=[^)]*(?:\(|$))', pieces[1].upper()) @@ -402,12 +416,12 @@ def privileges_revoke(cursor, user,host,db_table,priv,grant_option): # Escape '%' since mysql db.execute() uses a format string db_table = db_table.replace('%', '%%') if grant_option: - query = ["REVOKE GRANT OPTION ON %s" % mysql_quote_identifier(db_table, 'table')] + query = ["REVOKE GRANT OPTION ON %s" % db_table] query.append("FROM %s@%s") query = ' '.join(query) cursor.execute(query, (user, host)) priv_string = ",".join([p for p in priv if p not in ('GRANT', 'REQUIRESSL')]) - query = ["REVOKE %s ON %s" % (priv_string, mysql_quote_identifier(db_table, 'table'))] + query = ["REVOKE %s ON %s" % (priv_string, db_table)] query.append("FROM %s@%s") query = ' '.join(query) cursor.execute(query, (user, host)) @@ -417,7 +431,7 @@ def privileges_grant(cursor, user,host,db_table,priv): # specification of db and table often use a % (SQL wildcard) db_table = db_table.replace('%', '%%') priv_string = ",".join([p for p in priv if p not in ('GRANT', 'REQUIRESSL')]) - query = ["GRANT %s ON %s" % (priv_string, mysql_quote_identifier(db_table, 'table'))] + query = ["GRANT %s ON %s" % (priv_string, db_table)] query.append("TO %s@%s") if 'GRANT' in priv: query.append("WITH GRANT OPTION") @@ -476,12 +490,6 @@ def main(): if not mysqldb_found: module.fail_json(msg="the python mysqldb module is required") - if priv is not None: - try: - priv = privileges_unpack(priv) - except Exception, e: - module.fail_json(msg="invalid privileges string: %s" % str(e)) - cursor = None try: if check_implicit_admin: @@ -495,6 +503,16 @@ def main(): except Exception, e: module.fail_json(msg="unable to connect to database, check login_user and login_password are correct or %s has the credentials. Exception message: %s" % (config_file, e)) + if priv is not None: + try: + mode = get_mode(cursor) + except Exception, e: + module.fail_json(msg=str(e)) + try: + priv = privileges_unpack(priv, mode) + except Exception, e: + module.fail_json(msg="invalid privileges string: %s" % str(e)) + if state == "present": if user_exists(cursor, user, host, host_all): try: