Skip to content

Commit

Permalink
mysql_query: fix false change reports when IF NOT EXISTS clause is us…
Browse files Browse the repository at this point in the history
…ed (#322) (#374)

* mysql_query: fix false change reports when IF NOT EXISTS clause is used

* Fix

* Fix doc, add fragment

* Improve doc

(cherry picked from commit 6474610)

Co-authored-by: Andrew Klychkov <[email protected]>
  • Loading branch information
patchback[bot] and Andersson007 authored May 25, 2022
1 parent 46dc308 commit 0011798
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bugfixes:
- mysql_query - fix false change reports when ``IF EXISTS/IF NOT EXISTS`` clause is used (https://github.com/ansible-collections/community.mysql/issues/268).
32 changes: 28 additions & 4 deletions plugins/modules/mysql_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
description:
- SQL query to run. Multiple queries can be passed using YAML list syntax.
- Must be a string or YAML list containing strings.
- Note that if you use the C(IF EXISTS/IF NOT EXISTS) clauses in your query
and C(mysqlclient) connector, the module will report that
the state has been changed even if it has not. If it is important in your
workflow, use the C(PyMySQL) connector instead.
type: raw
required: yes
positional_args:
Expand Down Expand Up @@ -103,6 +107,8 @@
sample: [5, 1]
'''

import warnings

from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.mysql.plugins.module_utils.mysql import (
mysql_connect,
Expand Down Expand Up @@ -196,9 +202,22 @@ def main():
executed_queries = []
rowcount = []

already_exists = False
for q in query:
try:
cursor.execute(q, arguments)
with warnings.catch_warnings():
warnings.filterwarnings(action='error',
message='.*already exists*',
category=mysql_driver.Warning)

try:
cursor.execute(q, arguments)
except mysql_driver.Warning:
# When something is run with IF NOT EXISTS
# and there's "already exists" MySQL warning,
# set the flag as True.
# PyMySQL throws the warning, mysqlclinet does NOT.
already_exists = True

except Exception as e:
if not autocommit:
Expand All @@ -208,7 +227,8 @@ def main():
module.fail_json(msg="Cannot execute SQL '%s' args [%s]: %s" % (q, arguments, to_native(e)))

try:
query_result.append([dict(row) for row in cursor.fetchall()])
if not already_exists:
query_result.append([dict(row) for row in cursor.fetchall()])

except Exception as e:
if not autocommit:
Expand All @@ -224,8 +244,12 @@ def main():

for keyword in DDL_QUERY_KEYWORDS:
if keyword in q:
changed = True

if already_exists:
# Indicates the entity already exists
changed = False
already_exists = False # Reset flag
else:
changed = True
try:
executed_queries.append(cursor._last_executed)
except AttributeError:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,39 @@
- result is changed
- result.rowcount == [2]

# Issue https://github.com/ansible-collections/community.mysql/issues/268
- name: Create table
mysql_query:
<<: *mysql_params
login_db: '{{ test_db }}'
query: "CREATE TABLE issue268 (id int)"
single_transaction: yes

# Issue https://github.com/ansible-collections/community.mysql/issues/268
- name: Create table with IF NOT EXISTS
mysql_query:
<<: *mysql_params
login_db: '{{ test_db }}'
query: "CREATE TABLE IF NOT EXISTS issue268 (id int)"
single_transaction: yes
register: result

# Issue https://github.com/ansible-collections/community.mysql/issues/268
- assert:
that:
# PyMySQL driver throws a warning, so the following is correct
- result is not changed
when: connector.name.0 is search('pymysql')

# Issue https://github.com/ansible-collections/community.mysql/issues/268
- assert:
that:
# mysqlclient driver throws nothing, so it's impossible to figure out
# if the state was changed or not.
# We assume that it was for DDL queryes by default in the code
- result is changed
when: connector.name.0 is search('mysqlclient')

- name: Drop db {{ test_db }}
mysql_query:
<<: *mysql_params
Expand Down

0 comments on commit 0011798

Please sign in to comment.