From 9cf17827d25ea8c65b7096975325668c2bcc5be6 Mon Sep 17 00:00:00 2001
From: Laurent Indermuehle <laurent.indermuehle@pm.me>
Date: Wed, 13 Nov 2024 17:38:04 +0100
Subject: [PATCH] [WIP] Add tables count per database

---
 plugins/modules/mysql_info.py                 | 32 +++++---
 .../tasks/filter_databases_tables.yml         | 75 +++++++++++++++++++
 .../targets/test_mysql_info/tasks/main.yml    |  4 +
 3 files changed, 102 insertions(+), 9 deletions(-)
 create mode 100644 tests/integration/targets/test_mysql_info/tasks/filter_databases_tables.yml

diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py
index 3a30597..bed3f0c 100644
--- a/plugins/modules/mysql_info.py
+++ b/plugins/modules/mysql_info.py
@@ -35,7 +35,7 @@ options:
   exclude_fields:
     description:
     - List of fields which are not needed to collect.
-    - "Supports elements: C(db_size). Unsupported elements will be ignored."
+    - "Supports elements: C(db_size), C(db_table_count). Unsupported elements will be ignored."
     type: list
     elements: str
     version_added: '0.1.0'
@@ -656,15 +656,20 @@ class MySQL_Info(object):
 
     def __get_databases(self, exclude_fields, return_empty_dbs):
         """Get info about databases."""
-        if not exclude_fields:
-            query = ('SELECT table_schema AS "name", '
-                     'SUM(data_length + index_length) AS "size" '
-                     'FROM information_schema.TABLES GROUP BY table_schema')
-        else:
-            if 'db_size' in exclude_fields:
-                query = ('SELECT table_schema AS "name" '
-                         'FROM information_schema.TABLES GROUP BY table_schema')
 
+        cmd_start = 'SELECT table_schema AS "name"'
+        cmd_db_size = 'SUM(data_length + index_length) AS "size"'
+        cmd_db_table_count = 'COUNT(table_name) as "tables"'
+        cmd_end = ' FROM information_schema.TABLES GROUP BY table_schema'
+        cmd_start_and_fields = [cmd_start, cmd_db_size, cmd_db_table_count]
+
+        if exclude_fields and 'db_size' in exclude_fields:
+            cmd_start_and_fields.remove(cmd_db_size)
+
+        if exclude_fields and 'db_table_count' in exclude_fields:
+            cmd_start_and_fields.remove(cmd_db_table_count)
+
+        query = ', '.join(cmd_start_and_fields) + cmd_end
         res = self.__exec_sql(query)
 
         if res:
@@ -677,6 +682,12 @@ class MySQL_Info(object):
 
                     self.info['databases'][db['name']]['size'] = int(db['size'])
 
+                if not exclude_fields or 'db_table_count' not in exclude_fields:
+                    if db['tables'] is None:
+                        db['tables'] = 0
+
+                    self.info['databases'][db['name']]['tables'] = int(db['tables'])
+
         # If empty dbs are not needed in the returned dict, exit from the method
         if not return_empty_dbs:
             return None
@@ -691,6 +702,9 @@ class MySQL_Info(object):
                     if not exclude_fields or 'db_size' not in exclude_fields:
                         self.info['databases'][db['Database']]['size'] = 0
 
+                    if not exclude_fields or 'db_table_count' not in exclude_fields:
+                        self.info['databases'][db['Database']]['tables'] = 0
+
     def __exec_sql(self, query, ddl=False):
         """Execute SQL.
 
diff --git a/tests/integration/targets/test_mysql_info/tasks/filter_databases_tables.yml b/tests/integration/targets/test_mysql_info/tasks/filter_databases_tables.yml
new file mode 100644
index 0000000..5aa87f5
--- /dev/null
+++ b/tests/integration/targets/test_mysql_info/tasks/filter_databases_tables.yml
@@ -0,0 +1,75 @@
+---
+
+- module_defaults:
+    community.mysql.mysql_db: &mysql_defaults
+      login_user: "{{ mysql_user }}"
+      login_password: "{{ mysql_password }}"
+      login_host: "{{ mysql_host }}"
+      login_port: "{{ mysql_primary_port }}"
+    community.mysql.mysql_query: *mysql_defaults
+    community.mysql.mysql_info: *mysql_defaults
+    community.mysql.mysql_user: *mysql_defaults
+
+  block:
+
+    # ================================ Prepare ==============================
+    - name: Mysql_info users_info | Create databases
+      community.mysql.mysql_db:
+        name:
+          - db_tables_count_empty
+          - db_tables_count_1
+          - db_tables_count_2
+        state: present
+
+    - name: Mysql_info users_info | Create tables
+      community.mysql.mysql_query:
+        query:
+          - >-
+            CREATE TABLE IF NOT EXISTS db_tables_count_1.t1
+            (id int, name varchar(9))
+          - >-
+            CREATE TABLE IF NOT EXISTS db_tables_count_2.t1
+            (id int, name1 varchar(9))
+          - >-
+            CREATE TABLE IF NOT EXISTS db_tables_count_2.t2
+            (id int, name1 varchar(9))
+
+    # ================================== Tests ==============================
+
+    - name: Mysql_info users_info | Collect all databases fields
+      community.mysql.mysql_info:
+        filter:
+          - databases
+      register: result
+      # failed_when:
+      #   - TODO
+
+    - name: Mysql_info users_info | Collect all databases fields except db_size
+      community.mysql.mysql_info:
+        filter:
+          - databases
+        exclude_fileds:
+          - db_size
+      register: result
+      # failed_when:
+      #   - TODO
+
+    - name: Mysql_info users_info | Collect all databases fields except db_table_count
+      community.mysql.mysql_info:
+        filter:
+          - databases
+        exclude_fileds:
+          - db_table_count
+      register: result
+      # failed_when:
+      #   - TODO
+
+    # ================================== Cleanup ============================
+
+    - name: Mysql_info users_info | Cleanup databases
+      community.mysql.mysql_db:
+        name:
+          - db_tables_count_empty
+          - db_tables_count_1
+          - db_tables_count_2
+        state: present
diff --git a/tests/integration/targets/test_mysql_info/tasks/main.yml b/tests/integration/targets/test_mysql_info/tasks/main.yml
index 42350c6..bfe7708 100644
--- a/tests/integration/targets/test_mysql_info/tasks/main.yml
+++ b/tests/integration/targets/test_mysql_info/tasks/main.yml
@@ -221,6 +221,10 @@
         that:
           - result.databases.allviews.size == 0
 
+    - name: Import tasks file to tests tables count in database filter
+      ansible.builtin.import_tasks:
+        file: filter_databases_tables.yml
+
     - name: Import tasks file to tests users_info filter
       ansible.builtin.import_tasks:
         file: filter_users_info.yml