pystratum_mysql.backend.MySqlRoutineLoaderWorker   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 176
Duplicated Lines 0 %

Test Coverage

Coverage 31.25%

Importance

Changes 0
Metric Value
wmc 19
eloc 79
dl 0
loc 176
ccs 20
cts 64
cp 0.3125
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A MySqlRoutineLoaderWorker.__save_column_types_exact() 0 14 3
B MySqlRoutineLoaderWorker.__save_column_types_max_length() 0 26 6
A MySqlRoutineLoaderWorker._get_column_type() 0 9 1
A MySqlRoutineLoaderWorker.__init__() 0 21 1
A MySqlRoutineLoaderWorker._get_old_stored_routine_info() 0 8 2
A MySqlRoutineLoaderWorker._get_correct_sql_mode() 0 5 1
A MySqlRoutineLoaderWorker._read_configuration_file() 0 9 1
A MySqlRoutineLoaderWorker.create_routine_loader_helper() 0 21 1
A MySqlRoutineLoaderWorker._drop_obsolete_routines() 0 9 3
1 1
from configparser import ConfigParser
2 1
from typing import Any, Dict, List, Optional
3
4 1
from pystratum_backend.StratumIO import StratumIO
5
from pystratum_common.backend.CommonRoutineLoaderWorker import CommonRoutineLoaderWorker
6 1
7 1
from pystratum_mysql.backend.MySqlWorker import MySqlWorker
8 1
from pystratum_mysql.helper.MySqlRoutineLoaderHelper import MySqlRoutineLoaderHelper
9
10
11 1
class MySqlRoutineLoaderWorker(MySqlWorker, CommonRoutineLoaderWorker):
12
    """
13
    Class for loading stored routines into a MySQL instance from (pseudo) SQL files.
14
    """
15 1
    MAX_LENGTH_CHAR = 255
16
    """
17
    Maximum length of a varchar.
18
    """
19
20 1
    MAX_LENGTH_VARCHAR = 4096
21
    """
22
    Maximum length of a varchar.
23
    """
24
25 1
    MAX_LENGTH_BINARY = 255
26
    """
27
    Maximum length of a varbinary.
28
    """
29
30 1
    MAX_LENGTH_VARBINARY = 4096
31
    """
32
    Maximum length of a varbinary.
33
    """
34
35
    # ------------------------------------------------------------------------------------------------------------------
36 1
    def __init__(self, io: StratumIO, config: ConfigParser):
37
        """
38
        Object constructor.
39
40
        :param io: The output decorator.
41
        """
42
        MySqlWorker.__init__(self, io, config)
43
        CommonRoutineLoaderWorker.__init__(self, io, config)
44
45
        self._character_set_client: Optional[str] = None
46
        """
47
        The default character set under which the stored routine will be loaded and run.
48
        """
49
50
        self._collation_connection: Optional[str] = None
51
        """
52
        The default collate under which the stored routine will be loaded and run.
53
        """
54
55
        self._sql_mode: Optional[str] = None
56
        """
57
        
58
        """
59
60
    # ------------------------------------------------------------------------------------------------------------------
61 1
    def __save_column_types_exact(self, rows: List[Dict[str, Any]]) -> None:
62
        """
63
        Saves the exact column types as replace pairs.
64
65
        :param rows: The column types.
66
        """
67
        for row in rows:
68
            key = row['table_name'] + '.' + row['column_name'] + '%type'
69
70
            value = row['column_type']
71
            if row['character_set_name']:
72
                value += ' character set ' + row['character_set_name']
73
74
            self._add_replace_pair(key, value, False)
75
76
    # ------------------------------------------------------------------------------------------------------------------
77 1
    def __save_column_types_max_length(self, rows: List[Dict[str, Any]]) -> None:
78
        """
79
        Saves the column types with maximum length as replace pairs.
80
81
        :param rows: The column types.
82
        """
83
        for row in rows:
84
            key = row['table_name'] + '.' + row['column_name'] + '%max-type'
85
86
            if row['data_type'] == 'char':
87
                value = row['data_type'] + '(' + str(self.MAX_LENGTH_CHAR) + ')'
88
                value += ' character set ' + row['character_set_name']
89
                self._add_replace_pair(key, value, False)
90
91
            if row['data_type'] == 'varchar':
92
                value = row['data_type'] + '(' + str(self.MAX_LENGTH_VARCHAR) + ')'
93
                value += ' character set ' + row['character_set_name']
94
                self._add_replace_pair(key, value, False)
95
96
            elif row['data_type'] == 'binary':
97
                value = row['data_type'] + '(' + str(self.MAX_LENGTH_BINARY) + ')'
98
                self._add_replace_pair(key, value, False)
99
100
            elif row['data_type'] == 'varbinary':
101
                value = row['data_type'] + '(' + str(self.MAX_LENGTH_VARBINARY) + ')'
102
                self._add_replace_pair(key, value, False)
103
104
    # ------------------------------------------------------------------------------------------------------------------
105 1
    def _get_column_type(self) -> None:
106
        """
107
        Selects schema, table, column names and the column type from MySQL and saves them as replace pairs.
108
        """
109
        rows = self._dl.get_all_table_columns()
110
        self.__save_column_types_exact(rows)
111
        self.__save_column_types_max_length(rows)
112
113
        self._io.text('Selected {0} column types for substitution'.format(len(rows)))
114
115
    # ------------------------------------------------------------------------------------------------------------------
116 1
    def create_routine_loader_helper(self,
117
                                     routine_name: str,
118
                                     pystratum_old_metadata: Optional[Dict],
119
                                     rdbms_old_metadata: Optional[Dict]) -> MySqlRoutineLoaderHelper:
120
        """
121
        Creates a Routine Loader Helper object.
122
123
        :param routine_name: The name of the routine.
124
        :param pystratum_old_metadata: The old metadata of the stored routine from PyStratum.
125
        :param rdbms_old_metadata:  The old metadata of the stored routine from MySQL.
126
        """
127
        return MySqlRoutineLoaderHelper(self._io,
128
                                        self._dl,
129
                                        self._source_file_names[routine_name],
130
                                        self._source_file_encoding,
131
                                        pystratum_old_metadata,
132
                                        self._replace_pairs,
133
                                        rdbms_old_metadata,
134
                                        self._sql_mode,
135
                                        self._character_set_client,
136
                                        self._collation_connection)
137
138
    # ------------------------------------------------------------------------------------------------------------------
139
    def _get_old_stored_routine_info(self) -> None:
140
        """
141 1
        Retrieves information about all stored routines in the current schema.
142
        """
143
        rows = self._dl.get_routines()
144
        self._rdbms_old_metadata = {}
145
        for row in rows:
146
            self._rdbms_old_metadata[row['routine_name']] = row
147
148
    # ------------------------------------------------------------------------------------------------------------------
149
    def _get_correct_sql_mode(self) -> None:
150
        """
151 1
        Gets the SQL mode in the order as preferred by MySQL.
152
        """
153
        self._sql_mode = self._dl.get_correct_sql_mode(self._sql_mode)
154
155
    # ------------------------------------------------------------------------------------------------------------------
156
    def _drop_obsolete_routines(self) -> None:
157
        """
158 1
        Drops obsolete stored routines (i.e. stored routines that exits in the current schema but for
159
        which we don't have a source file).
160
        """
161
        for routine_name, values in self._rdbms_old_metadata.items():
162
            if routine_name not in self._source_file_names:
163
                self._io.text("Dropping {0} <dbo>{1}</dbo>".format(values['routine_type'].lower(), routine_name))
164
                self._dl.drop_stored_routine(values['routine_type'], routine_name)
165
166
    # ------------------------------------------------------------------------------------------------------------------
167
    def _read_configuration_file(self) -> None:
168
        """
169 1
        Reads parameters from the configuration file.
170
        """
171
        CommonRoutineLoaderWorker._read_configuration_file(self)
172
173
        self._character_set_client = self._config.get('database', 'character_set_client', fallback='utf-8')
174
        self._collation_connection = self._config.get('database', 'collation_connection', fallback='utf8_general_ci')
175
        self._sql_mode = self._config.get('database', 'sql_mode')
176
177
# ----------------------------------------------------------------------------------------------------------------------
178