__init__.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import asyncio
  2. from inspect import signature
  3. from typing import Optional, Union, Dict, Any
  4. from urllib.parse import urlparse, parse_qs
  5. import clickhouse_connect.driver.ctypes
  6. from clickhouse_connect.driver.client import Client
  7. from clickhouse_connect.driver.common import dict_copy
  8. from clickhouse_connect.driver.exceptions import ProgrammingError
  9. from clickhouse_connect.driver.httpclient import HttpClient
  10. from clickhouse_connect.driver.asyncclient import AsyncClient
  11. # pylint: disable=too-many-arguments,too-many-locals,too-many-branches
  12. def create_client(*,
  13. host: str = None,
  14. username: str = None,
  15. password: str = '',
  16. database: str = '__default__',
  17. interface: Optional[str] = None,
  18. port: int = 0,
  19. secure: Union[bool, str] = False,
  20. dsn: Optional[str] = None,
  21. settings: Optional[Dict[str, Any]] = None,
  22. generic_args: Optional[Dict[str, Any]] = None,
  23. **kwargs) -> Client:
  24. """
  25. The preferred method to get a ClickHouse Connect Client instance
  26. :param host: The hostname or IP address of the ClickHouse server. If not set, localhost will be used.
  27. :param username: The ClickHouse username. If not set, the default ClickHouse user will be used.
  28. :param password: The password for username.
  29. :param database: The default database for the connection. If not set, ClickHouse Connect will use the
  30. default database for username.
  31. :param interface: Must be http or https. Defaults to http, or to https if port is set to 8443 or 443
  32. :param port: The ClickHouse HTTP or HTTPS port. If not set will default to 8123, or to 8443 if secure=True
  33. or interface=https.
  34. :param secure: Use https/TLS. This overrides inferred values from the interface or port arguments.
  35. :param dsn: A string in standard DSN (Data Source Name) format. Other connection values (such as host or user)
  36. will be extracted from this string if not set otherwise.
  37. :param settings: ClickHouse server settings to be used with the session/every request
  38. :param generic_args: Used internally to parse DBAPI connection strings into keyword arguments and ClickHouse settings.
  39. It is not recommended to use this parameter externally.
  40. :param kwargs -- Recognized keyword arguments (used by the HTTP client), see below
  41. :param compress: Enable compression for ClickHouse HTTP inserts and query results. True will select the preferred
  42. compression method (lz4). A str of 'lz4', 'zstd', 'brotli', or 'gzip' can be used to use a specific compression type
  43. :param query_limit: Default LIMIT on returned rows. 0 means no limit
  44. :param connect_timeout: Timeout in seconds for the http connection
  45. :param send_receive_timeout: Read timeout in seconds for http connection
  46. :param client_name: client_name prepended to the HTTP User Agent header. Set this to track client queries
  47. in the ClickHouse system.query_log.
  48. :param send_progress: Deprecated, has no effect. Previous functionality is now automatically determined
  49. :param verify: Verify the server certificate in secure/https mode
  50. :param ca_cert: If verify is True, the file path to Certificate Authority root to validate ClickHouse server
  51. certificate, in .pem format. Ignored if verify is False. This is not necessary if the ClickHouse server
  52. certificate is trusted by the operating system. To trust the maintained list of "global" public root
  53. certificates maintained by the Python 'certifi' package, set ca_cert to 'certifi'
  54. :param client_cert: File path to a TLS Client certificate in .pem format. This file should contain any
  55. applicable intermediate certificates
  56. :param client_cert_key: File path to the private key for the Client Certificate. Required if the private key
  57. is not included the Client Certificate key file
  58. :param session_id ClickHouse session id. If not specified and the common setting 'autogenerate_session_id'
  59. is True, the client will generate a UUID1 session id
  60. :param pool_mgr Optional urllib3 PoolManager for this client. Useful for creating separate connection
  61. pools for multiple client endpoints for applications with many clients
  62. :param http_proxy http proxy address. Equivalent to setting the HTTP_PROXY environment variable
  63. :param https_proxy https proxy address. Equivalent to setting the HTTPS_PROXY environment variable
  64. :param server_host_name This is the server host name that will be checked against a TLS certificate for
  65. validity. This option can be used if using an ssh_tunnel or other indirect means to an ClickHouse server
  66. where the `host` argument refers to the tunnel or proxy and not the actual ClickHouse server
  67. :param autogenerate_session_id If set, this will override the 'autogenerate_session_id' common setting.
  68. :return: ClickHouse Connect Client instance
  69. """
  70. if dsn:
  71. parsed = urlparse(dsn)
  72. username = username or parsed.username
  73. password = password or parsed.password
  74. host = host or parsed.hostname
  75. port = port or parsed.port
  76. if parsed.path and (not database or database == '__default__'):
  77. database = parsed.path[1:].split('/')[0]
  78. database = database or parsed.path
  79. for k, v in parse_qs(parsed.query).items():
  80. kwargs[k] = v[0]
  81. use_tls = str(secure).lower() == 'true' or interface == 'https' or (not interface and port in (443, 8443))
  82. if not host:
  83. host = 'localhost'
  84. if not interface:
  85. interface = 'https' if use_tls else 'http'
  86. port = port or default_port(interface, use_tls)
  87. if username is None and 'user' in kwargs:
  88. username = kwargs.pop('user')
  89. if username is None and 'user_name' in kwargs:
  90. username = kwargs.pop('user_name')
  91. if password and username is None:
  92. username = 'default'
  93. if 'compression' in kwargs and 'compress' not in kwargs:
  94. kwargs['compress'] = kwargs.pop('compression')
  95. settings = settings or {}
  96. if interface.startswith('http'):
  97. if generic_args:
  98. client_params = signature(HttpClient).parameters
  99. for name, value in generic_args.items():
  100. if name in client_params:
  101. kwargs[name] = value
  102. elif name == 'compression':
  103. if 'compress' not in kwargs:
  104. kwargs['compress'] = value
  105. else:
  106. if name.startswith('ch_'):
  107. name = name[3:]
  108. settings[name] = value
  109. return HttpClient(interface, host, port, username, password, database, settings=settings, **kwargs)
  110. raise ProgrammingError(f'Unrecognized client type {interface}')
  111. def default_port(interface: str, secure: bool):
  112. if interface.startswith('http'):
  113. return 8443 if secure else 8123
  114. raise ValueError('Unrecognized ClickHouse interface')
  115. async def create_async_client(*,
  116. host: str = None,
  117. username: str = None,
  118. password: str = '',
  119. database: str = '__default__',
  120. interface: Optional[str] = None,
  121. port: int = 0,
  122. secure: Union[bool, str] = False,
  123. dsn: Optional[str] = None,
  124. settings: Optional[Dict[str, Any]] = None,
  125. generic_args: Optional[Dict[str, Any]] = None,
  126. **kwargs) -> AsyncClient:
  127. """
  128. The preferred method to get an async ClickHouse Connect Client instance.
  129. For sync version, see create_client.
  130. Unlike sync version, the 'autogenerate_session_id' setting by default is False.
  131. :param host: The hostname or IP address of the ClickHouse server. If not set, localhost will be used.
  132. :param username: The ClickHouse username. If not set, the default ClickHouse user will be used.
  133. :param password: The password for username.
  134. :param database: The default database for the connection. If not set, ClickHouse Connect will use the
  135. default database for username.
  136. :param interface: Must be http or https. Defaults to http, or to https if port is set to 8443 or 443
  137. :param port: The ClickHouse HTTP or HTTPS port. If not set will default to 8123, or to 8443 if secure=True
  138. or interface=https.
  139. :param secure: Use https/TLS. This overrides inferred values from the interface or port arguments.
  140. :param dsn: A string in standard DSN (Data Source Name) format. Other connection values (such as host or user)
  141. will be extracted from this string if not set otherwise.
  142. :param settings: ClickHouse server settings to be used with the session/every request
  143. :param generic_args: Used internally to parse DBAPI connection strings into keyword arguments and ClickHouse settings.
  144. It is not recommended to use this parameter externally
  145. :param kwargs -- Recognized keyword arguments (used by the HTTP client), see below
  146. :param compress: Enable compression for ClickHouse HTTP inserts and query results. True will select the preferred
  147. compression method (lz4). A str of 'lz4', 'zstd', 'brotli', or 'gzip' can be used to use a specific compression type
  148. :param query_limit: Default LIMIT on returned rows. 0 means no limit
  149. :param connect_timeout: Timeout in seconds for the http connection
  150. :param send_receive_timeout: Read timeout in seconds for http connection
  151. :param client_name: client_name prepended to the HTTP User Agent header. Set this to track client queries
  152. in the ClickHouse system.query_log.
  153. :param send_progress: Deprecated, has no effect. Previous functionality is now automatically determined
  154. :param verify: Verify the server certificate in secure/https mode
  155. :param ca_cert: If verify is True, the file path to Certificate Authority root to validate ClickHouse server
  156. certificate, in .pem format. Ignored if verify is False. This is not necessary if the ClickHouse server
  157. certificate is trusted by the operating system. To trust the maintained list of "global" public root
  158. certificates maintained by the Python 'certifi' package, set ca_cert to 'certifi'
  159. :param client_cert: File path to a TLS Client certificate in .pem format. This file should contain any
  160. applicable intermediate certificates
  161. :param client_cert_key: File path to the private key for the Client Certificate. Required if the private key
  162. is not included the Client Certificate key file
  163. :param session_id ClickHouse session id. If not specified and the common setting 'autogenerate_session_id'
  164. is True, the client will generate a UUID1 session id
  165. :param pool_mgr Optional urllib3 PoolManager for this client. Useful for creating separate connection
  166. pools for multiple client endpoints for applications with many clients
  167. :param http_proxy http proxy address. Equivalent to setting the HTTP_PROXY environment variable
  168. :param https_proxy https proxy address. Equivalent to setting the HTTPS_PROXY environment variable
  169. :param server_host_name This is the server host name that will be checked against a TLS certificate for
  170. validity. This option can be used if using an ssh_tunnel or other indirect means to an ClickHouse server
  171. where the `host` argument refers to the tunnel or proxy and not the actual ClickHouse server
  172. :param autogenerate_session_id If set, this will override the 'autogenerate_session_id' common setting.
  173. :return: ClickHouse Connect Client instance
  174. """
  175. def _create_client():
  176. if 'autogenerate_session_id' not in kwargs:
  177. kwargs['autogenerate_session_id'] = False
  178. return create_client(host=host, username=username, password=password, database=database, interface=interface,
  179. port=port, secure=secure, dsn=dsn, settings=settings, generic_args=generic_args, **kwargs)
  180. loop = asyncio.get_running_loop()
  181. _client = await loop.run_in_executor(None, _create_client)
  182. return AsyncClient(client=_client)