1import signal
2
3from plain.models.backends.base.client import BaseDatabaseClient
4
5
6class DatabaseClient(BaseDatabaseClient):
7 executable_name = "mysql"
8
9 @classmethod
10 def settings_to_cmd_args_env(cls, settings_dict, parameters):
11 args = [cls.executable_name]
12 env = None
13 database = settings_dict["OPTIONS"].get(
14 "database",
15 settings_dict["OPTIONS"].get("db", settings_dict["NAME"]),
16 )
17 user = settings_dict["OPTIONS"].get("user", settings_dict["USER"])
18 password = settings_dict["OPTIONS"].get(
19 "password",
20 settings_dict["OPTIONS"].get("passwd", settings_dict["PASSWORD"]),
21 )
22 host = settings_dict["OPTIONS"].get("host", settings_dict["HOST"])
23 port = settings_dict["OPTIONS"].get("port", settings_dict["PORT"])
24 server_ca = settings_dict["OPTIONS"].get("ssl", {}).get("ca")
25 client_cert = settings_dict["OPTIONS"].get("ssl", {}).get("cert")
26 client_key = settings_dict["OPTIONS"].get("ssl", {}).get("key")
27 defaults_file = settings_dict["OPTIONS"].get("read_default_file")
28 charset = settings_dict["OPTIONS"].get("charset")
29 # Seems to be no good way to set sql_mode with CLI.
30
31 if defaults_file:
32 args += ["--defaults-file=%s" % defaults_file]
33 if user:
34 args += ["--user=%s" % user]
35 if password:
36 # The MYSQL_PWD environment variable usage is discouraged per
37 # MySQL's documentation due to the possibility of exposure through
38 # `ps` on old Unix flavors but --password suffers from the same
39 # flaw on even more systems. Usage of an environment variable also
40 # prevents password exposure if the subprocess.run(check=True) call
41 # raises a CalledProcessError since the string representation of
42 # the latter includes all of the provided `args`.
43 env = {"MYSQL_PWD": password}
44 if host:
45 if "/" in host:
46 args += ["--socket=%s" % host]
47 else:
48 args += ["--host=%s" % host]
49 if port:
50 args += ["--port=%s" % port]
51 if server_ca:
52 args += ["--ssl-ca=%s" % server_ca]
53 if client_cert:
54 args += ["--ssl-cert=%s" % client_cert]
55 if client_key:
56 args += ["--ssl-key=%s" % client_key]
57 if charset:
58 args += ["--default-character-set=%s" % charset]
59 if database:
60 args += [database]
61 args.extend(parameters)
62 return args, env
63
64 def runshell(self, parameters):
65 sigint_handler = signal.getsignal(signal.SIGINT)
66 try:
67 # Allow SIGINT to pass to mysql to abort queries.
68 signal.signal(signal.SIGINT, signal.SIG_IGN)
69 super().runshell(parameters)
70 finally:
71 # Restore the original SIGINT handler.
72 signal.signal(signal.SIGINT, sigint_handler)