1414 select ,
1515 table ,
1616)
17- from sqlalchemy .exc import ProgrammingError
17+ from sqlalchemy .exc import NoSuchTableError , ProgrammingError
1818from sqlalchemy .ext .asyncio import AsyncConnection , AsyncEngine , create_async_engine
1919
2020from middleware .sql_to_arc .models import (
@@ -66,7 +66,7 @@ async def _get_db_columns(conn: AsyncConnection, view_name: str) -> set[str] | N
6666 try :
6767 columns = await conn .run_sync (lambda sync_conn : inspect (sync_conn ).get_columns (view_name ))
6868 return {col ["name" ] for col in columns }
69- except (ProgrammingError , sqlalchemy . exc . NoSuchTableError ):
69+ except (ProgrammingError , NoSuchTableError ):
7070 logger .warning ('Table or view "%s" does not exist or is not accessible.' , view_name )
7171 return None
7272
@@ -184,7 +184,8 @@ def _validate_and_map(
184184 entity_name : str ,
185185 ) -> RowModel | None :
186186 try :
187- return model .model_validate (dict (row ))
187+ validated : RowModel = model .model_validate (dict (row ))
188+ return validated
188189 except ValidationError as error :
189190 logger .warning ("Skipping %s due to validation error: %s" , entity_name , error )
190191 return None
@@ -198,9 +199,13 @@ async def stream_investigations(
198199 view_name = InvestigationRow .__view_name__
199200 try :
200201 async with self .engine .connect () as conn :
201- # Use SQLAlchemy select() and limit() for dialect-agnosticism
202- t = table (view_name )
203- stmt = select (t ).execution_options (stream_results = True )
202+ # Use literal_column("*") to ensure SQLAlchemy generates 'SELECT *'
203+ # instead of '"vInvestigation"."*"'
204+ stmt : sqlalchemy .Select [Any ] = (
205+ select (sqlalchemy .literal_column ("*" ))
206+ .select_from (table (view_name ))
207+ .execution_options (stream_results = True )
208+ )
204209 if limit :
205210 stmt = stmt .limit (limit )
206211
@@ -235,10 +240,14 @@ async def _stream_by_investigation(
235240 view_name = model .__view_name__
236241 try :
237242 async with self .engine .connect () as conn :
238- # Use SQLAlchemy select() and in_() for dialect-agnosticism
239- t = table (view_name )
243+ # Use literal_column("*") to select all columns
240244 c_inv_ref : sqlalchemy .ColumnElement [Any ] = column ("investigation_ref" )
241- stmt = select (t ).where (c_inv_ref .in_ (investigation_ids )).execution_options (stream_results = True )
245+ stmt : sqlalchemy .Select [Any ] = (
246+ select (sqlalchemy .literal_column ("*" ))
247+ .select_from (table (view_name ))
248+ .where (c_inv_ref .in_ (investigation_ids ))
249+ .execution_options (stream_results = True )
250+ )
242251
243252 result = await conn .stream (stmt )
244253 async for row in result .mappings ():
@@ -278,9 +287,14 @@ async def stream_annotation_tables(self, investigation_ids: list[str]) -> AsyncG
278287 view_name = "vAnnotationTable"
279288 try :
280289 async with self .engine .connect () as conn :
281- t = table ( view_name )
290+ # Use literal_column("*") to select all columns
282291 c_inv_ref : sqlalchemy .ColumnElement [Any ] = column ("investigation_ref" )
283- stmt = select (t ).where (c_inv_ref .in_ (investigation_ids )).execution_options (stream_results = True )
292+ stmt : sqlalchemy .Select [Any ] = (
293+ select (sqlalchemy .literal_column ("*" ))
294+ .select_from (table (view_name ))
295+ .where (c_inv_ref .in_ (investigation_ids ))
296+ .execution_options (stream_results = True )
297+ )
284298
285299 result = await conn .stream (stmt )
286300 async for row in result .mappings ():
0 commit comments