|
1 | 1 | import asyncio |
2 | 2 | import importlib |
3 | 3 | import logging |
| 4 | +import re |
4 | 5 | from contextlib import suppress |
5 | 6 | from os.path import dirname, join |
6 | 7 | from typing import Any, Dict, Iterator, List, Optional, Tuple |
|
16 | 17 | from dipdup.http import HTTPGateway |
17 | 18 | from dipdup.utils import iter_files, iter_models |
18 | 19 |
|
| 20 | +_get_fields_query = ''' |
| 21 | +query introspectionQuery($name: String!) { |
| 22 | + __type(name: $name) { |
| 23 | + kind |
| 24 | + name |
| 25 | + fields { |
| 26 | + name |
| 27 | + description |
| 28 | + type { |
| 29 | + name |
| 30 | + kind |
| 31 | + ofType { |
| 32 | + name |
| 33 | + kind |
| 34 | + } |
| 35 | + } |
| 36 | + } |
| 37 | + } |
| 38 | +} |
| 39 | +'''.replace( |
| 40 | + '\n', ' ' |
| 41 | +).replace( |
| 42 | + ' ', '' |
| 43 | +) |
| 44 | + |
19 | 45 |
|
20 | 46 | @dataclass |
21 | 47 | class Field: |
@@ -263,43 +289,30 @@ def _merge_metadata(self, existing: List[Dict[str, Any]], generated: List[Dict[s |
263 | 289 | generated_dict = {key(t): t for t in generated} |
264 | 290 | return list({**existing_dict, **generated_dict}.values()) |
265 | 291 |
|
266 | | - async def _get_fields(self, name: str = 'query_root') -> List[Field]: |
267 | | - query = ''' |
268 | | -query introspectionQuery($name: String!) { |
269 | | - __type(name: $name) { |
270 | | - kind |
271 | | - name |
272 | | - fields { |
273 | | - name |
274 | | - description |
275 | | - type { |
276 | | - name |
277 | | - kind |
278 | | - ofType { |
279 | | - name |
280 | | - kind |
281 | | - } |
282 | | - } |
283 | | - } |
284 | | - } |
285 | | -} |
286 | | - '''.replace( |
287 | | - '\n', ' ' |
288 | | - ).replace( |
289 | | - ' ', '' |
290 | | - ) |
| 292 | + async def _get_fields_json(self, name: str) -> List[Dict[str, Any]]: |
291 | 293 | result = await self._hasura_request( |
292 | 294 | endpoint='graphql', |
293 | 295 | json={ |
294 | | - 'query': query, |
| 296 | + 'query': _get_fields_query, |
295 | 297 | 'variables': {'name': name}, |
296 | 298 | }, |
297 | 299 | ) |
298 | 300 | try: |
299 | | - fields_json = result['data']['__type']['fields'] |
| 301 | + return result['data']['__type']['fields'] |
300 | 302 | except TypeError as e: |
301 | 303 | raise HasuraError(f'Unknown table `{name}`') from e |
302 | 304 |
|
| 305 | + async def _get_fields(self, name: str = 'query_root') -> List[Field]: |
| 306 | + |
| 307 | + try: |
| 308 | + fields_json = await self._get_fields_json(name) |
| 309 | + except HasuraError: |
| 310 | + # NOTE: An issue with decamelizing the table name? |
| 311 | + # NOTE: dex_quotes_15m -> dexQuotes15m -> dex_quotes15m -> FAIL |
| 312 | + # NOTE: Let's prefix every numeric with underscore. Won't help in complex cases but worth a try. |
| 313 | + alternative_name = ''.join([f"_{w}" if w.isnumeric() else w for w in re.split(r'(\d+)', name)]) |
| 314 | + fields_json = await self._get_fields_json(alternative_name) |
| 315 | + |
303 | 316 | fields = [] |
304 | 317 | for field_json in fields_json: |
305 | 318 | # NOTE: Exclude autogenerated aggregate and pk fields |
|
0 commit comments