client.py 2.9 KB

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