Skip to content
29 changes: 27 additions & 2 deletions salt/modules/mysql.py
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,29 @@ def _execute(cur, qry, args=None):
return cur.execute(qry, args)


def _sanitize_comments(content):
# Remove comments which might affect line by line parsing
# Regex should remove any text begining with # (or --) not inside of ' or "
content = re.sub(
r"""(['"](?:[^'"]+|(?<=\\)['"])*['"])|#[^\n]*""",
lambda m: m.group(1) or "",
content,
re.S,
)
content = re.sub(
r"""(['"](?:[^'"]+|(?<=\\)['"])*['"])|--[^\n]*""",
lambda m: m.group(1) or "",
content,
re.S,
)
cleaned = ""
for line in content.splitlines():
line = line.strip()
if line != "":
cleaned += line + "\n"
return cleaned


def query(database, query, **connection_args):
"""
Run an arbitrary SQL query and return the results or
Expand Down Expand Up @@ -823,9 +846,10 @@ def file_query(database, file_name, **connection_args):
"rows affected": 0,
"query time": {"raw": 0},
}

contents = _sanitize_comments(contents)
# Walk the each line of the sql file to get accurate row affected results
for line in contents.splitlines():
if re.match(r"--", line): # ignore sql comments
continue
if not re.search(r"[^-;]+;", line): # keep appending lines that don't end in ;
query_string = query_string + line
else:
Expand All @@ -849,6 +873,7 @@ def file_query(database, file_name, **connection_args):
ret["results"].append(query_result["results"])
if "rows affected" in query_result:
ret["rows affected"] += query_result["rows affected"]

ret["query time"]["human"] = (
six.text_type(round(float(ret["query time"]["raw"]), 2)) + "s"
)
Expand Down
10 changes: 8 additions & 2 deletions tests/integration/files/file/base/mysql/update_query.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
CREATE TABLE test_update (a INT);
insert into test_update values (1);
/*
multiline
comment
*/
CREATE TABLE test_update (a INT); # end of line comment
# example comment
insert into test_update values (1); -- ending comment
-- another comment type
update test_update set a=2 where a=1;
25 changes: 25 additions & 0 deletions tests/unit/modules/test_mysql.py
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,31 @@ def test_plugin_status(self):
"auth_socket",
)

def test_sanitize_comment(self):
"""
Test comment sanitization
"""
input_data = """/*
multiline
comment
*/
CREATE TABLE test_update (a VARCHAR(25)); # end of line comment
# example comment
insert into test_update values ("some #hash value"); -- ending comment
insert into test_update values ("crazy -- not comment"); -- another ending comment
-- another comment type
"""
expected_response = """/*
multiline
comment
*/
CREATE TABLE test_update (a VARCHAR(25));
insert into test_update values ("some #hash value");
insert into test_update values ("crazy -- not comment");
"""
output = mysql._sanitize_comments(input_data)
self.assertEqual(output, expected_response)

def _test_call(self, function, expected_sql, *args, **kwargs):
connect_mock = MagicMock()
with patch.object(mysql, "_connect", connect_mock):
Expand Down