async def _execute(self, query: str, *args) -> AsyncGenerator[Record, None]: query_type = self.query_type(query) if query_type == QueryTypes.FETCH: query += " FORMAT TSVWithNamesAndTypes" if args: if query_type != QueryTypes.INSERT: raise ChClientError( "It is possible to pass arguments only for INSERT queries" ) params = {**self.params, "query": query} if 'FORMAT JSONEachRow' in query: data = json2ch(*args) else: data = rows2ch(*args) else: params = self.params data = query.encode() async with self._session.post( self.url, params=params, data=data ) as resp: # type: client.ClientResponse if resp.status != 200: raise ChClientError((await resp.read()).decode(errors='replace')) if query_type == QueryTypes.FETCH: rf = RecordsFabric( names=await resp.content.readline(), tps=await resp.content.readline(), ) async for line in resp.content: yield rf.new(line)
async def _execute( self, query: str, *args, json: bool = False, query_params: Optional[Dict[str, Any]] = None, ) -> AsyncGenerator[Record, None]: query_params = self._prepare_query_params(query_params) query = query.format(**query_params) need_fetch, is_json, statement_type = self._parse_squery(query) if not is_json and json: query += " FORMAT JSONEachRow" is_json = True if not is_json and need_fetch: query += " FORMAT TSVWithNamesAndTypes" if args: if statement_type != 'INSERT': raise ChClientError( "It is possible to pass arguments only for INSERT queries") params = {**self.params, "query": query} if is_json: data = json2ch(*args, dumps=self._json.dumps) else: data = rows2ch(*args) else: params = self.params data = query.encode() async with self._session.post( self.url, params=params, data=data) as resp: # type: client.ClientResponse if resp.status != 200: raise ChClientError((await resp.read()).decode(errors='replace')) if need_fetch: if is_json: rf = FromJsonFabric(loads=self._json.loads) async for line in resp.content: yield rf.new(line) else: rf = RecordsFabric( names=await resp.content.readline(), tps=await resp.content.readline(), ) async for line in resp.content: yield rf.new(line)
def what_py_type(name: str, container: bool = False) -> BaseType: """ Returns needed type class from clickhouse type name """ name = name.strip() try: return CH_TYPES_MAPPING[name.split("(")[0]](name, container=container) except KeyError: raise ChClientError(f"Unrecognized type name: '{name}'")
def py2ch(value): try: return PY_TYPES_MAPPING[type(value)](value) except KeyError: raise ChClientError( f"Unrecognized type: '{type(value)}'. " f"The value type should be exactly one of " f"int, float, str, dt.date, dt.datetime, tuple, list, uuid.UUID (or None). " f"No subclasses yet.")
async def _execute( self, query: str, *args, json: bool = False, query_params: Optional[Dict[str, Any]] = None, query_id: str = None, ) -> AsyncGenerator[Record, None]: query_params = self._prepare_query_params(query_params) query = query.format(**query_params) need_fetch, is_json, statement_type = self._parse_squery(query) if not is_json and json: query += " FORMAT JSONEachRow" is_json = True if not is_json and need_fetch: query += " FORMAT TSVWithNamesAndTypes" if args: if statement_type != 'INSERT': raise ChClientError( "It is possible to pass arguments only for INSERT queries" ) params = {**self.params, "query": query} if is_json: data = json2ch(*args, dumps=self._json.dumps) else: data = rows2ch(*args) else: params = {**self.params} data = query.encode() if query_id is not None: params["query_id"] = query_id if need_fetch: response = self._http_client.post_return_lines( url=self.url, params=params, data=data ) if is_json: rf = FromJsonFabric(loads=self._json.loads) async for line in response: yield rf.new(line) else: rf = RecordsFabric( names=await response.__anext__(), tps=await response.__anext__(), ) async for line in response: yield rf.new(line) else: await self._http_client.post_no_return( url=self.url, params=params, data=data )
def what_py_type(name: str, container: bool = False) -> BaseType: """Returns needed type class from clickhouse type name""" name = name.strip() try: if name.startswith('SimpleAggregateFunction') or name.startswith( 'AggregateFunction' ): ch_type = re.findall(r',(.*)\)', name)[0].strip() else: ch_type = name.split("(")[0] return CH_TYPES_MAPPING[ch_type](name, container=container) except KeyError: raise ChClientError(f"Unrecognized type name: '{name}'")
def choose_http_client(session): try: import aiohttp if session is None or isinstance(session, aiohttp.ClientSession): from aiochclient.http_clients.aiohttp import AiohttpHttpClient return AiohttpHttpClient except ImportError: pass try: import httpx if session is None or isinstance(session, httpx.AsyncClient): from aiochclient.http_clients.httpx import HttpxHttpClient return HttpxHttpClient except ImportError: pass raise ChClientError('Async http client heeded. Please install aiohttp or httpx')
async def _check_response(resp): if resp.status != 200: raise ChClientError(await _read_error_body(resp))