|
16 | 16 | from models_library.users import UserID |
17 | 17 | from psycopg2.errors import ForeignKeyViolation |
18 | 18 | from pydantic import PositiveInt, TypeAdapter, ValidationError |
| 19 | +from simcore_postgres_database.utils import as_postgres_sql_query_str |
19 | 20 | from simcore_postgres_database.utils_repos import pass_or_acquire_connection |
20 | 21 | from simcore_postgres_database.utils_services import create_select_latest_services_query |
21 | 22 | from sqlalchemy import sql |
@@ -478,55 +479,66 @@ async def get_service_history_page( |
478 | 479 | offset: int | None = None, |
479 | 480 | ) -> tuple[PositiveInt, list[ReleaseDBGet]]: |
480 | 481 |
|
481 | | - base_query = ( |
| 482 | + base_subquery = ( |
| 483 | + # Search on service (key, *) for (product_name, user_id w/ access) |
482 | 484 | sql.select( |
483 | 485 | services_meta_data.c.key, |
484 | 486 | services_meta_data.c.version, |
485 | | - services_meta_data.c.version_display, |
486 | | - services_meta_data.c.deprecated, |
487 | | - services_meta_data.c.created, |
488 | | - services_compatibility.c.custom_policy.label( |
489 | | - "compatibility_policy" |
490 | | - ), # CompatiblePolicyDict | None |
491 | 487 | ) |
492 | 488 | .select_from( |
493 | | - # joins because access-rights might change per version |
494 | 489 | services_meta_data.join( |
495 | 490 | services_access_rights, |
496 | 491 | (services_meta_data.c.key == services_access_rights.c.key) |
497 | 492 | & ( |
498 | 493 | services_meta_data.c.version == services_access_rights.c.version |
499 | 494 | ), |
500 | | - ) |
501 | | - .join( |
| 495 | + ).join( |
502 | 496 | user_to_groups, |
503 | 497 | (user_to_groups.c.gid == services_access_rights.c.gid), |
504 | 498 | ) |
505 | | - .outerjoin( |
506 | | - services_compatibility, |
507 | | - (services_meta_data.c.key == services_compatibility.c.key) |
508 | | - & ( |
509 | | - services_meta_data.c.version == services_compatibility.c.version |
510 | | - ), |
511 | | - ) |
512 | 499 | ) |
513 | 500 | .where( |
514 | 501 | (services_meta_data.c.key == key) |
515 | 502 | & (services_access_rights.c.product_name == product_name) |
516 | 503 | & (user_to_groups.c.uid == user_id) |
517 | 504 | & AccessRightsClauses.can_read |
518 | 505 | ) |
519 | | - .distinct() |
520 | | - ) |
| 506 | + ).subquery() |
521 | 507 |
|
522 | | - subquery = base_query.subquery() |
523 | | - count_query = sql.select(sql.func.count()).select_from(subquery) |
| 508 | + # Query to count the TOTAL number of rows |
| 509 | + count_query = sql.select(sql.func.count()).select_from(base_subquery) |
| 510 | + _logger.debug("count_query=\n%s", as_postgres_sql_query_str(count_query)) |
524 | 511 |
|
| 512 | + # Query to retrieve page with additional columns, ordering, offset, and limit |
525 | 513 | page_query = ( |
526 | | - base_query.order_by(sql.desc(by_version(base_query.c.version))) |
| 514 | + sql.select( |
| 515 | + services_meta_data.c.key, |
| 516 | + services_meta_data.c.version, |
| 517 | + services_meta_data.c.version_display, |
| 518 | + services_meta_data.c.deprecated, |
| 519 | + services_meta_data.c.created, |
| 520 | + # CompatiblePolicyDict | None |
| 521 | + services_compatibility.c.custom_policy.label("compatibility_policy"), |
| 522 | + ) |
| 523 | + .select_from( |
| 524 | + # NOTE: these joins are avoided in count_query |
| 525 | + base_subquery.join( |
| 526 | + services_meta_data, |
| 527 | + (base_subquery.c.key == services_meta_data.c.key) |
| 528 | + & (base_subquery.c.version == services_meta_data.c.version), |
| 529 | + ).outerjoin( |
| 530 | + services_compatibility, |
| 531 | + (services_meta_data.c.key == services_compatibility.c.key) |
| 532 | + & ( |
| 533 | + services_meta_data.c.version == services_compatibility.c.version |
| 534 | + ), |
| 535 | + ) |
| 536 | + ) |
| 537 | + .order_by(sql.desc(by_version(services_meta_data.c.version))) |
527 | 538 | .offset(offset) |
528 | 539 | .limit(limit) |
529 | 540 | ) |
| 541 | + _logger.debug("page_query=\n%s", as_postgres_sql_query_str(page_query)) |
530 | 542 |
|
531 | 543 | async with pass_or_acquire_connection(self.db_engine) as conn: |
532 | 544 | total_count: PositiveInt = await conn.scalar(count_query) or 0 |
|
0 commit comments