Skip to content

Commit

Permalink
postgresql_query: add query_all_results ret value (#886)
Browse files Browse the repository at this point in the history
* postgresql_query: add query_all_results ret value

* add changelog fragment

* fix CI

* fix doc

* Update plugins/modules/database/postgresql/postgresql_query.py

Co-authored-by: Tobias Birkefeld <t@craxs.de>

* Update plugins/modules/database/postgresql/postgresql_query.py

Co-authored-by: Tobias Birkefeld <t@craxs.de>

* fix doc

Co-authored-by: Tobias Birkefeld <t@craxs.de>
(cherry picked from commit 8267fd3)
  • Loading branch information
Andersson007 authored and Patchback committed Oct 20, 2020
1 parent 788dc4b commit c98f35f
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 39 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/886-postgresql_query_add_ret_vals.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- postgresql_query - add ``query_list`` and ``query_all_results`` return values (https://github.com/ansible-collections/community.general/issues/838).
115 changes: 79 additions & 36 deletions plugins/modules/database/postgresql/postgresql_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
type: dict
path_to_script:
description:
- Path to SQL script on the remote host.
- Returns result of the last query in the script.
- Path to a SQL script on the target machine.
- If the script contains several queries, they must be semicolon-separated.
- Mutually exclusive with I(query).
type: path
session_role:
Expand Down Expand Up @@ -175,23 +175,48 @@

RETURN = r'''
query:
description: Query that was tried to be executed.
description:
- Executed query.
- When reading several queries from a file, it contains only the last one.
returned: always
type: str
sample: 'SELECT * FROM bar'
statusmessage:
description: Attribute containing the message returned by the command.
description:
- Attribute containing the message returned by the command.
- When reading several queries from a file, it contains a message of the last one.
returned: always
type: str
sample: 'INSERT 0 1'
query_result:
description:
- List of dictionaries in column:value form representing returned rows.
returned: changed
- When running queries from a file, returns result of the last query.
returned: always
type: list
elements: dict
sample: [{"Column": "Value1"},{"Column": "Value2"}]
query_list:
description:
- List of executed queries.
Useful when reading several queries from a file.
returned: always
type: list
elements: str
sample: ['SELECT * FROM foo', 'SELECT * FROM bar']
query_all_results:
description:
- List containing results of all queries executed (one sublist for every query).
Useful when reading several queries from a file.
returned: always
type: list
elements: list
sample: [[{"Column": "Value1"},{"Column": "Value2"}], [{"Column": "Value1"},{"Column": "Value2"}]]
rowcount:
description: Number of affected rows.
description:
- Number of produced or affected rows.
- When using a script with multiple queries,
it contains a total number of produced or affected rows.
returned: changed
type: int
sample: 5
Expand Down Expand Up @@ -318,12 +343,19 @@ def main():
elif named_args:
named_args = convert_elements_to_pg_arrays(named_args)

query_list = []
if path_to_script:
try:
with open(path_to_script, 'rb') as f:
query = to_native(f.read())
if ';' in query:
query_list = [q for q in query.split(';') if q != '\n']
else:
query_list.append(query)
except Exception as e:
module.fail_json(msg="Cannot read file '%s' : %s" % (path_to_script, to_native(e)))
else:
query_list.append(query)

conn_params = get_conn_params(module, module.params)
db_connection = connect_to_db(module, conn_params, autocommit=autocommit)
Expand All @@ -345,45 +377,54 @@ def main():
# Set defaults:
changed = False

query_all_results = []
rowcount = 0
statusmessage = ''

# Execute query:
try:
cursor.execute(query, arguments)
except Exception as e:
if not autocommit:
db_connection.rollback()
for query in query_list:
try:
cursor.execute(query, arguments)
statusmessage = cursor.statusmessage
if cursor.rowcount > 0:
rowcount += cursor.rowcount

cursor.close()
db_connection.close()
module.fail_json(msg="Cannot execute SQL '%s' %s: %s" % (query, arguments, to_native(e)))
try:
query_result = [dict(row) for row in cursor.fetchall()]

statusmessage = cursor.statusmessage
rowcount = cursor.rowcount
except Psycopg2ProgrammingError as e:
if to_native(e) == 'no results to fetch':
query_result = {}

try:
query_result = [dict(row) for row in cursor.fetchall()]
except Psycopg2ProgrammingError as e:
if to_native(e) == 'no results to fetch':
query_result = {}
except Exception as e:
module.fail_json(msg="Cannot fetch rows from cursor: %s" % to_native(e))

except Exception as e:
module.fail_json(msg="Cannot fetch rows from cursor: %s" % to_native(e))
query_all_results.append(query_result)

if 'SELECT' not in statusmessage:
if 'UPDATE' in statusmessage or 'INSERT' in statusmessage or 'DELETE' in statusmessage:
s = statusmessage.split()
if len(s) == 3:
if statusmessage.split()[2] != '0':
changed = True
if 'SELECT' not in statusmessage:
if 'UPDATE' in statusmessage or 'INSERT' in statusmessage or 'DELETE' in statusmessage:
s = statusmessage.split()
if len(s) == 3:
if s[2] != '0':
changed = True

elif len(s) == 2:
if s[1] != '0':
changed = True

elif len(s) == 2:
if statusmessage.split()[1] != '0':
else:
changed = True

else:
changed = True

else:
changed = True
except Exception as e:
if not autocommit:
db_connection.rollback()

else:
changed = True
cursor.close()
db_connection.close()
module.fail_json(msg="Cannot execute SQL '%s' %s: %s, query list: %s" % (query, arguments, to_native(e), query_list))

if module.check_mode:
db_connection.rollback()
Expand All @@ -394,9 +435,11 @@ def main():
kw = dict(
changed=changed,
query=cursor.query,
query_list=query_list,
statusmessage=statusmessage,
query_result=query_result,
rowcount=rowcount if rowcount >= 0 else 0,
query_all_results=query_all_results,
rowcount=rowcount,
)

cursor.close()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,11 @@
that:
- result is changed
- result.query == 'ANALYZE test_table'
- result.query_list == ['ANALYZE test_table']
- result.rowcount == 0
- result.statusmessage == 'ANALYZE'
- result.query_result == {}
- result.query_all_results == [{}]

- name: postgresql_query - run queries from SQL script
become_user: '{{ pg_user }}'
Expand All @@ -79,10 +81,12 @@
- assert:
that:
- result is not changed
- result.query == "SELECT version();\nSELECT story FROM test_table\nWHERE id = 1 OR story = 'Данные';\n"
- result.rowcount == 1
- result.statusmessage == 'SELECT 1' or result.statusmessage == 'SELECT'
- result.query == "\nSELECT story FROM test_table\nWHERE id = 1 OR story = 'Данные'"
- result.query_result[0].story == 'first'
- result.query_all_results[0][0].version is search('PostgreSQL')
- result.query_all_results[1][0].story == 'first'
- result.rowcount == 2
- result.statusmessage == 'SELECT 1' or result.statusmessage == 'SELECT'
when: sql_file_created

- name: postgresql_query - simple select query to test_table
Expand Down

0 comments on commit c98f35f

Please sign in to comment.