Repository: rucio/rucio

Issue:
Oracle hints for list_bad_* have a plus too much
The faulty rendered SQL looks like this:

```
SELECT /*+ + index(replicas REPLICAS_STATE_IDX) */ atlas_rucio......
```
Needs fix in get_bad_replicas_backlog and list_bad_replicas.


Discussion:

Resolving patch:
diff --git a/lib/rucio/core/replica.py b/lib/rucio/core/replica.py
--- a/lib/rucio/core/replica.py
+++ b/lib/rucio/core/replica.py
@@ -191,7 +191,7 @@ def __exist_replicas(rse_id, replicas, session=None):
                                       func.max(case([(models.BadReplicas.state == BadFilesStatus.SUSPICIOUS, 0),
                                                      (models.BadReplicas.state == BadFilesStatus.BAD, 1)],
                                                     else_=0))).\
-                    with_hint(models.RSEFileAssociation, "+ index(replicas REPLICAS_PATH_IDX", 'oracle').\
+                    with_hint(models.RSEFileAssociation, "INDEX(REPLICAS REPLICAS_PATH_IDX", 'oracle').\
                     outerjoin(models.BadReplicas,
                               and_(models.RSEFileAssociation.scope == models.BadReplicas.scope,
                                    models.RSEFileAssociation.name == models.BadReplicas.name,
@@ -528,7 +528,7 @@ def get_bad_replicas_backlog(force_refresh=False, session=None):
         if session.bind.dialect.name == 'oracle':
             # The filter(text...)) is needed otherwise, SQLA uses bind variables and the index is not used.
             query = session.query(func.count(models.RSEFileAssociation.rse_id), models.RSEFileAssociation.rse_id).\
-                with_hint(models.RSEFileAssociation, "+ index(replicas REPLICAS_STATE_IDX)", 'oracle').\
+                with_hint(models.RSEFileAssociation, "INDEX(REPLICAS REPLICAS_STATE_IDX)", 'oracle').\
                 filter(text("CASE WHEN (%sreplicas.state != 'A') THEN %sreplicas.rse_id END IS NOT NULL" % (schema_dot,
                                                                                                             schema_dot))). \
                 filter(models.RSEFileAssociation.state == ReplicaState.BAD)
@@ -567,7 +567,7 @@ def list_bad_replicas(limit=10000, thread=None, total_threads=None, rses=None, s
         query = session.query(models.RSEFileAssociation.scope,
                               models.RSEFileAssociation.name,
                               models.RSEFileAssociation.rse_id).\
-            with_hint(models.RSEFileAssociation, "+ index(replicas REPLICAS_STATE_IDX)", 'oracle').\
+            with_hint(models.RSEFileAssociation, "INDEX(REPLICAS REPLICAS_STATE_IDX)", 'oracle').\
             filter(text("CASE WHEN (%sreplicas.state != 'A') THEN %sreplicas.rse_id END IS NOT NULL" % (schema_dot,
                                                                                                         schema_dot))). \
             filter(models.RSEFileAssociation.state == ReplicaState.BAD)
diff --git a/lib/rucio/core/request.py b/lib/rucio/core/request.py
--- a/lib/rucio/core/request.py
+++ b/lib/rucio/core/request.py
@@ -473,15 +473,15 @@ def list_transfer_requests_and_source_replicas(
                                                    sub_requests.c.name == models.RSEFileAssociation.name,
                                                    models.RSEFileAssociation.state == ReplicaState.AVAILABLE,
                                                    sub_requests.c.dest_rse_id != models.RSEFileAssociation.rse_id)) \
-        .with_hint(models.RSEFileAssociation, "+ index(replicas REPLICAS_PK)", 'oracle') \
+        .with_hint(models.RSEFileAssociation, "INDEX(REPLICAS REPLICAS_PK)", 'oracle') \
         .outerjoin(models.RSE, and_(models.RSE.id == models.RSEFileAssociation.rse_id,
                                     models.RSE.deleted == false())) \
         .outerjoin(models.Source, and_(sub_requests.c.id == models.Source.request_id,
                                        models.RSE.id == models.Source.rse_id)) \
-        .with_hint(models.Source, "+ index(sources SOURCES_PK)", 'oracle') \
+        .with_hint(models.Source, "INDEX(SOURCES SOURCES_PK)", 'oracle') \
         .outerjoin(models.Distance, and_(sub_requests.c.dest_rse_id == models.Distance.dest_rse_id,
                                          models.RSEFileAssociation.rse_id == models.Distance.src_rse_id)) \
-        .with_hint(models.Distance, "+ index(distances DISTANCES_PK)", 'oracle')
+        .with_hint(models.Distance, "INDEX(DISTANCES DISTANCES_PK)", 'oracle')
 
     # if transfertool specified, select only the requests where the source rses are set up for the transfer tool
     if transfertool:


Test patch: