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
* 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:
parent
788dc4bc23
commit
bb2ad10eef
3 changed files with 89 additions and 40 deletions
|
@ -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).
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue