Issue 59955: add array handling to postgresql_query module (#60559)

* Issue 59955: add array handling to postgresql_query module

* Issue 59955: add array handling to postgresql_query module, improvements

* Issue 59955: add array handling to postgresql_query module, fix example comment
This commit is contained in:
Andrey Klychkov 2019-08-22 09:53:29 +03:00 committed by Felix Fontein
parent 5fec75a91a
commit 191068a286
3 changed files with 172 additions and 0 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- postgresql_query - Add array handling for positional_args and named_args parameters (https://github.com/ansible/ansible/issues/59955).

View file

@ -30,11 +30,13 @@ options:
positional_args:
description:
- List of values to be passed as positional arguments to the query.
When the value is a list, it will be converted to PostgreSQL array.
- Mutually exclusive with I(named_args).
type: list
named_args:
description:
- Dictionary of key-value arguments to pass to the query.
When the value is a list, it will be converted to PostgreSQL array.
- Mutually exclusive with I(positional_args).
type: dict
path_to_script:
@ -119,6 +121,22 @@ EXAMPLES = r'''
query: INSERT INTO test_table (array_column) VALUES (%s)
positional_args:
- '{1,2,3}'
# Pass list and string vars as positional_args
- name: Set vars
set_fact:
my_list:
- 1
- 2
- 3
my_arr: '{1, 2, 3}'
- name: Select from test table by passing positional_args as arrays
postgresql_query:
query: SELECT * FROM test_array_table WHERE arr_col1 = %s AND arr_col2 = %s
positional_args:
- '{{ my_list }}'
- '{{ my_arr|string }}'
'''
RETURN = r'''
@ -161,12 +179,50 @@ from ansible.module_utils.postgres import (
postgres_common_argument_spec,
)
from ansible.module_utils._text import to_native
from ansible.module_utils.six import iteritems
# ===========================================
# Module execution.
#
def list_to_pg_array(elem):
"""Convert the passed list to PostgreSQL array
represented as a string.
Args:
elem (list): List that needs to be converted.
Returns:
elem (str): String representation of PostgreSQL array.
"""
elem = str(elem).strip('[]')
elem = '{' + elem + '}'
return elem
def convert_elements_to_pg_arrays(obj):
"""Convert list elements of the passed object
to PostgreSQL arrays represented as strings.
Args:
obj (dict or list): Object whose elements need to be converted.
Returns:
obj (dict or list): Object with converted elements.
"""
if isinstance(obj, dict):
for (key, elem) in iteritems(obj):
if isinstance(elem, list):
obj[key] = list_to_pg_array(elem)
elif isinstance(obj, list):
for i, elem in enumerate(obj):
if isinstance(elem, list):
obj[i] = list_to_pg_array(elem)
return obj
def main():
argument_spec = postgres_common_argument_spec()
@ -201,6 +257,12 @@ def main():
if path_to_script and query:
module.fail_json(msg="path_to_script is mutually exclusive with query")
if positional_args:
positional_args = convert_elements_to_pg_arrays(positional_args)
elif named_args:
named_args = convert_elements_to_pg_arrays(named_args)
if path_to_script:
try:
query = open(path_to_script, 'r').read()

View file

@ -360,3 +360,111 @@
- result.rowcount == 0
- result.statusmessage == 'VACUUM'
- result.query_result == {}
#
# Issue 59955
#
- name: postgresql_query - create test table for issue 59955
become_user: "{{ pg_user }}"
become: yes
postgresql_table:
login_user: "{{ pg_user }}"
login_db: postgres
name: test_array_table
columns:
- arr_col int[]
when: postgres_version_resp.stdout is version('9.4', '>=')
- set_fact:
my_list:
- 1
- 2
- 3
my_arr: '{1, 2, 3}'
when: postgres_version_resp.stdout is version('9.4', '>=')
- name: postgresql_query - insert array into test table by positional args
become_user: "{{ pg_user }}"
become: yes
postgresql_query:
login_user: "{{ pg_user }}"
login_db: postgres
query: INSERT INTO test_array_table (arr_col) VALUES (%s)
positional_args:
- '{{ my_list }}'
register: result
when: postgres_version_resp.stdout is version('9.4', '>=')
- assert:
that:
- result is changed
- result.query == "INSERT INTO test_array_table (arr_col) VALUES ('{1, 2, 3}')"
when: postgres_version_resp.stdout is version('9.4', '>=')
- name: postgresql_query - select array from test table by passing positional_args
become_user: "{{ pg_user }}"
become: yes
postgresql_query:
login_user: "{{ pg_user }}"
login_db: postgres
query: SELECT * FROM test_array_table WHERE arr_col = %s
positional_args:
- '{{ my_list }}'
register: result
when: postgres_version_resp.stdout is version('9.4', '>=')
- assert:
that:
- result is not changed
- result.query == "SELECT * FROM test_array_table WHERE arr_col = '{1, 2, 3}'"
- result.rowcount == 1
when: postgres_version_resp.stdout is version('9.4', '>=')
- name: postgresql_query - select array from test table by passing named_args
become_user: "{{ pg_user }}"
become: yes
postgresql_query:
login_user: "{{ pg_user }}"
login_db: postgres
query: SELECT * FROM test_array_table WHERE arr_col = %(arr_val)s
named_args:
arr_val:
- '{{ my_list }}'
register: result
when: postgres_version_resp.stdout is version('9.4', '>=')
- assert:
that:
- result is not changed
- result.query == "SELECT * FROM test_array_table WHERE arr_col = '{1, 2, 3}'"
- result.rowcount == 1
when: postgres_version_resp.stdout is version('9.4', '>=')
- name: postgresql_query - select array from test table by passing positional_args as a string
become_user: "{{ pg_user }}"
become: yes
postgresql_query:
login_user: "{{ pg_user }}"
login_db: postgres
query: SELECT * FROM test_array_table WHERE arr_col = %s
positional_args:
- '{{ my_arr|string }}'
register: result
when: postgres_version_resp.stdout is version('9.4', '>=')
- assert:
that:
- result is not changed
- result.query == "SELECT * FROM test_array_table WHERE arr_col = '{1, 2, 3}'"
- result.rowcount == 1
when: postgres_version_resp.stdout is version('9.4', '>=')
- name: postgresql_query - clean up
become_user: "{{ pg_user }}"
become: yes
postgresql_table:
login_user: "{{ pg_user }}"
login_db: postgres
name: test_array_table
state: absent
when: postgres_version_resp.stdout is version('9.4', '>=')