
    Vhv0                         d dl mZmZmZ eZdZdZdZd dl	m
Z
mZ d dlZd dlZdZ	 d dlZdZd	 Zd
 Zd Zedk(  r e        yy# e$ r  ej$                         ZdZY 1w xY w)    )absolute_importdivisionprint_functiona  
module: mssql_script

short_description: Execute SQL scripts on a MSSQL database

version_added: "4.0.0"

description:
  - Execute SQL scripts on a MSSQL database.
extends_documentation_fragment:
  - community.general.attributes

attributes:
  check_mode:
    support: partial
    details:
      - The script will not be executed in check mode.
  diff_mode:
    support: none

options:
  name:
    description: Database to run script against.
    aliases: [db]
    default: ''
    type: str
  login_user:
    description: The username used to authenticate with.
    type: str
  login_password:
    description: The password used to authenticate with.
    type: str
  login_host:
    description: Host running the database.
    type: str
    required: true
  login_port:
    description: Port of the MSSQL server. Requires O(login_host) be defined as well.
    default: 1433
    type: int
  script:
    description:
      - The SQL script to be executed.
      - Script can contain multiple SQL statements. Multiple Batches can be separated by V(GO) command.
      - Each batch must return at least one result set.
    required: true
    type: str
  transaction:
    description:
      - If transactional mode is requested, start a transaction and commit the change only if the script succeed. Otherwise,
        rollback the transaction.
      - If transactional mode is not requested (default), automatically commit the change.
    type: bool
    default: false
    version_added: 8.4.0
  output:
    description:
      - With V(default) each row will be returned as a list of values. See RV(query_results).
      - Output format V(dict) will return dictionary with the column names as keys. See RV(query_results_dict).
      - V(dict) requires named columns to be returned by each query otherwise an error is thrown.
    choices: ["dict", "default"]
    default: 'default'
    type: str
  params:
    description: |-
      Parameters passed to the script as SQL parameters.
      (Query V('SELECT %(name\)s"') with V(example: '{"name": "John Doe"}).)'.
    type: dict
notes:
  - Requires the pymssql Python package on the remote host. For Ubuntu, this is as easy as C(pip install pymssql) (See M(ansible.builtin.pip)).
requirements:
  - pymssql

author:
  - Kris Budde (@kbudde)
aY  
- name: Check DB connection
  community.general.mssql_script:
    login_user: "{{ mssql_login_user }}"
    login_password: "{{ mssql_login_password }}"
    login_host: "{{ mssql_host }}"
    login_port: "{{ mssql_port }}"
    db: master
    script: "SELECT 1"

- name: Query with parameter
  community.general.mssql_script:
    login_user: "{{ mssql_login_user }}"
    login_password: "{{ mssql_login_password }}"
    login_host: "{{ mssql_host }}"
    login_port: "{{ mssql_port }}"
    script: |
      SELECT name, state_desc FROM sys.databases WHERE name = %(dbname)s
    params:
      dbname: msdb
  register: result_params
- assert:
    that:
      - result_params.query_results[0][0][0][0] == 'msdb'
      - result_params.query_results[0][0][0][1] == 'ONLINE'

- name: Query within a transaction
  community.general.mssql_script:
    login_user: "{{ mssql_login_user }}"
    login_password: "{{ mssql_login_password }}"
    login_host: "{{ mssql_host }}"
    login_port: "{{ mssql_port }}"
    script: |
      UPDATE sys.SomeTable SET desc = 'some_table_desc' WHERE name = %(dbname)s
      UPDATE sys.AnotherTable SET desc = 'another_table_desc' WHERE name = %(dbname)s
    transaction: true
    params:
      dbname: msdb

- name: two batches with default output
  community.general.mssql_script:
    login_user: "{{ mssql_login_user }}"
    login_password: "{{ mssql_login_password }}"
    login_host: "{{ mssql_host }}"
    login_port: "{{ mssql_port }}"
    script: |
      SELECT 'Batch 0 - Select 0'
      SELECT 'Batch 0 - Select 1'
      GO
      SELECT 'Batch 1 - Select 0'
  register: result_batches
- assert:
    that:
      - result_batches.query_results | length == 2 # two batch results
      - result_batches.query_results[0] | length == 2 # two selects in first batch
      - result_batches.query_results[0][0] | length == 1 # one row in first select
      - result_batches.query_results[0][0][0] | length == 1 # one column in first row
      - result_batches.query_results[0][0][0][0] == 'Batch 0 - Select 0' # each row contains a list of values.

- name: two batches with dict output
  community.general.mssql_script:
    login_user: "{{ mssql_login_user }}"
    login_password: "{{ mssql_login_password }}"
    login_host: "{{ mssql_host }}"
    login_port: "{{ mssql_port }}"
    output: dict
    script: |
      SELECT 'Batch 0 - Select 0' as b0s0
      SELECT 'Batch 0 - Select 1' as b0s1
      GO
      SELECT 'Batch 1 - Select 0' as b1s0
  register: result_batches_dict
- assert:
    that:
      - result_batches_dict.query_results_dict | length == 2 # two batch results
      - result_batches_dict.query_results_dict[0] | length == 2 # two selects in first batch
      - result_batches_dict.query_results_dict[0][0] | length == 1 # one row in first select
      - result_batches_dict.query_results_dict[0][0][0]['b0s0'] == 'Batch 0 - Select 0' # column 'b0s0' of first row
a  
query_results:
  description: List of batches (queries separated by V(GO) keyword).
  type: list
  elements: list
  returned: success and O(output=default)
  sample: [[[["Batch 0 - Select 0"]], [["Batch 0 - Select 1"]]], [[["Batch 1 - Select 0"]]]]
  contains:
    queries:
      description:
        - List of result sets of each query.
        - If a query returns no results, the results of this and all the following queries will not be included in the output.
        - Use the V(GO) keyword in O(script) to separate queries.
      type: list
      elements: list
      contains:
        rows:
          description: List of rows returned by query.
          type: list
          elements: list
          contains:
            column_value:
              description:
                - List of column values.
                - Any non-standard JSON type is converted to string.
              type: list
              example: ["Batch 0 - Select 0"]
              returned: success, if output is default
query_results_dict:
  description: List of batches (queries separated by V(GO) keyword).
  type: list
  elements: list
  returned: success and O(output=dict)
  sample: [[[["Batch 0 - Select 0"]], [["Batch 0 - Select 1"]]], [[["Batch 1 - Select 0"]]]]
  contains:
    queries:
      description:
        - List of result sets of each query.
        - If a query returns no results, the results of this and all the following queries will not be included in the output.
          Use V(GO) keyword to separate queries.
      type: list
      elements: list
      contains:
        rows:
          description: List of rows returned by query.
          type: list
          elements: list
          contains:
            column_dict:
              description:
                - Dictionary of column names and values.
                - Any non-standard JSON type is converted to string.
              type: dict
              example: {"col_name": "Batch 0 - Select 0"}
              returned: success, if output is dict
)AnsibleModulemissing_required_libNTFc                     t        |       S N)str)os    r/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/general/plugins/modules/mssql_script.pyclean_outputr      s    q6M    c                  ~   t        t        ddgd      t               t        d      t        d      t        dd	
      t        d      t        dddg      t        d      t        dd
      	      } t        d      }t        | d      }t        s |j                  t	        d      t
               |j                  d   }|j                  d   }|j                  d   }|j                  d   }|j                  d   }|j                  d   }|j                  d   }	|j                  d   }
|j                  d   }|}|d	k7  r|d|}|||j                  d        	 t        j                  ||||!      }|j                         }j                  |        d&}|	dk(  r|j                  d'      }d(}g }g }|j                  d      D ]k  }|j                         d)k(  r|j                         j!                         d*k7  r|j#                  |       J|j#                  dj%                  |             g }m t'        |      d+kD  r |j#                  dj%                  |             d|d,<   |j(                  r |j*                  d3i | g }|D ]^  }	 j-                  ||
       g }|j/                         }|r$|j#                  |       |j/                         }|r$|j#                  |       ` |r|j7                          t9        j:                  t9        j<                  |t>        2            }|||<    |j*                  d3i | y # t        $ rR}d"t        |      v r(|j                  \  }}|j                  d#|d$|        n|j                  d%        Y d }~d }~ww xY w# t        $ r}t1        |      j2                  d-k(  r t        |      d.k(  r|j#                  g        nK|r|j5                          t1        |      j2                  d/t        |      } |j                  d3d0||d1| Y d }~d }~ww xY w)4NFdb )requiredaliasesdefaultT)no_log)r   inti  )typer   r   dict)r   choices)r   bool)	name
login_userlogin_password
login_host
login_portscriptoutputparamstransaction)changed)argument_specsupports_check_modepymssql)msg	exceptionr   r   r   r   r   r    r!   r"   r#   :zHwhen supplying login_user argument, login_password must also be provided)r(   )userpasswordhostdatabasezUnknown databasezERROR:  zunable to connect, check login_user and login_password are correct, or alternatively check your @sysconfdir@/freetds.conf / ${HOME}/.freetds.confquery_results)as_dictquery_results_dictu   ﻿GOr   r$   OperationalErrorz=Statement not executed or executed statement has no resultsetz: zquery failed)r(   queryerror)r    ) r   r   MSSQL_FOUND	fail_jsonr   PYMSSQL_IMP_ERRr"   r'   connectcursor	Exceptionr
   args
autocommit
splitlinesstripupperappendjoinlen
check_mode	exit_jsonexecutefetchallr   __name__rollbackcommitjsonloadsdumpsr   )module_argsresultmoduler   r   r   r   r   r    r!   
sql_paramsr#   login_querystringconnr<   eerrnoerrstrquery_results_keyqueriescurrent_batch	statementr0   r5   
qry_resultrows	error_msgqry_resultss                               r   
run_modulera      s!   54&"=64(&UD1T"I	/BC fe4
K F ! F 1"1 	 	3 
v	B|,J]]#34N|,J|,J]]8$F]]8$Fx(J--.K"T'1:>."8Z 	 	\
Vn;LWY[ 	OOO$'T*0 GM&&t, 	??( ??""$,  +NN277=12M =Arww}-.F9"6"M ]	]NN5*-J??$D!!$'(    ,]4  **TZZ|LMK +FFvQ  VQ'FFME65&!AB "U VVb  	] Q  $66AYY$$R( MMO(,Q(8(8#a&A	   \^5	\U[\	]s9    )M A	N%N%	N"ANN"%	P<.BP77P<c                      t                y r	   )ra   r7   r   r   mainrc   l  s    Lr   __main__)
__future__r   r   r   r   __metaclass__DOCUMENTATIONEXAMPLESRETURNansible.module_utils.basicr   r   	tracebackrM   r:   r'   r8   ImportError
format_excr   ra   rc   rJ   r7   r   r   <module>rn      s    C BKZN`7
r K  
 Kxv zF U  *i**,OKs   A AA