1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

postgresql_query: add query_all_results ret value (#886) (#1131)

* 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 8267fd3809)

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
This commit is contained in:
patchback[bot] 2020-10-20 10:37:40 +03:00 committed by GitHub
parent 788dc4bc23
commit bb2ad10eef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 40 deletions

View file

@ -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).

View file

@ -38,8 +38,8 @@ options:
type: dict type: dict
path_to_script: path_to_script:
description: description:
- Path to SQL script on the remote host. - Path to a SQL script on the target machine.
- Returns result of the last query in the script. - If the script contains several queries, they must be semicolon-separated.
- Mutually exclusive with I(query). - Mutually exclusive with I(query).
type: path type: path
session_role: session_role:
@ -175,23 +175,48 @@ EXAMPLES = r'''
RETURN = r''' RETURN = r'''
query: 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 returned: always
type: str type: str
sample: 'SELECT * FROM bar' sample: 'SELECT * FROM bar'
statusmessage: 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 returned: always
type: str type: str
sample: 'INSERT 0 1' sample: 'INSERT 0 1'
query_result: query_result:
description: description:
- List of dictionaries in column:value form representing returned rows. - 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 type: list
elements: dict
sample: [{"Column": "Value1"},{"Column": "Value2"}] 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: 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 returned: changed
type: int type: int
sample: 5 sample: 5
@ -318,12 +343,19 @@ def main():
elif named_args: elif named_args:
named_args = convert_elements_to_pg_arrays(named_args) named_args = convert_elements_to_pg_arrays(named_args)
query_list = []
if path_to_script: if path_to_script:
try: try:
with open(path_to_script, 'rb') as f: with open(path_to_script, 'rb') as f:
query = to_native(f.read()) 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: except Exception as e:
module.fail_json(msg="Cannot read file '%s' : %s" % (path_to_script, to_native(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) conn_params = get_conn_params(module, module.params)
db_connection = connect_to_db(module, conn_params, autocommit=autocommit) db_connection = connect_to_db(module, conn_params, autocommit=autocommit)
@ -345,22 +377,21 @@ def main():
# Set defaults: # Set defaults:
changed = False changed = False
query_all_results = []
rowcount = 0
statusmessage = ''
# Execute query: # Execute query:
for query in query_list:
try: try:
cursor.execute(query, arguments) cursor.execute(query, arguments)
except Exception as e:
if not autocommit:
db_connection.rollback()
cursor.close()
db_connection.close()
module.fail_json(msg="Cannot execute SQL '%s' %s: %s" % (query, arguments, to_native(e)))
statusmessage = cursor.statusmessage statusmessage = cursor.statusmessage
rowcount = cursor.rowcount if cursor.rowcount > 0:
rowcount += cursor.rowcount
try: try:
query_result = [dict(row) for row in cursor.fetchall()] query_result = [dict(row) for row in cursor.fetchall()]
except Psycopg2ProgrammingError as e: except Psycopg2ProgrammingError as e:
if to_native(e) == 'no results to fetch': if to_native(e) == 'no results to fetch':
query_result = {} query_result = {}
@ -368,15 +399,17 @@ def main():
except Exception as e: except Exception as e:
module.fail_json(msg="Cannot fetch rows from cursor: %s" % to_native(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 'SELECT' not in statusmessage:
if 'UPDATE' in statusmessage or 'INSERT' in statusmessage or 'DELETE' in statusmessage: if 'UPDATE' in statusmessage or 'INSERT' in statusmessage or 'DELETE' in statusmessage:
s = statusmessage.split() s = statusmessage.split()
if len(s) == 3: if len(s) == 3:
if statusmessage.split()[2] != '0': if s[2] != '0':
changed = True changed = True
elif len(s) == 2: elif len(s) == 2:
if statusmessage.split()[1] != '0': if s[1] != '0':
changed = True changed = True
else: else:
@ -385,6 +418,14 @@ def main():
else: else:
changed = True changed = True
except Exception as e:
if not autocommit:
db_connection.rollback()
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: if module.check_mode:
db_connection.rollback() db_connection.rollback()
else: else:
@ -394,9 +435,11 @@ def main():
kw = dict( kw = dict(
changed=changed, changed=changed,
query=cursor.query, query=cursor.query,
query_list=query_list,
statusmessage=statusmessage, statusmessage=statusmessage,
query_result=query_result, query_result=query_result,
rowcount=rowcount if rowcount >= 0 else 0, query_all_results=query_all_results,
rowcount=rowcount,
) )
cursor.close() cursor.close()

View file

@ -58,9 +58,11 @@
that: that:
- result is changed - result is changed
- result.query == 'ANALYZE test_table' - result.query == 'ANALYZE test_table'
- result.query_list == ['ANALYZE test_table']
- result.rowcount == 0 - result.rowcount == 0
- result.statusmessage == 'ANALYZE' - result.statusmessage == 'ANALYZE'
- result.query_result == {} - result.query_result == {}
- result.query_all_results == [{}]
- name: postgresql_query - run queries from SQL script - name: postgresql_query - run queries from SQL script
become_user: '{{ pg_user }}' become_user: '{{ pg_user }}'
@ -79,10 +81,12 @@
- assert: - assert:
that: that:
- result is not changed - result is not changed
- result.query == "SELECT version();\nSELECT story FROM test_table\nWHERE id = 1 OR story = 'Данные';\n" - result.query == "\nSELECT story FROM test_table\nWHERE id = 1 OR story = 'Данные'"
- result.rowcount == 1
- result.statusmessage == 'SELECT 1' or result.statusmessage == 'SELECT'
- result.query_result[0].story == 'first' - 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 when: sql_file_created
- name: postgresql_query - simple select query to test_table - name: postgresql_query - simple select query to test_table