@@ -41,6 +41,11 @@ class PilotAgentsDB(DB):
4141 "VO" ,
4242 }
4343
44+ # Number of values inserted into the in-memory temp tables per batch in
45+ # getPilotInfo. Keeping batches bounded avoids overflowing MEMORY tables
46+ # (ERROR 1114: The table is full) when querying large pilot reference lists.
47+ PILOT_INFO_BATCH_SIZE = 10000
48+
4449 def __init__ (self , parentLogger = None ):
4550 super ().__init__ ("PilotAgentsDB" , "WorkloadManagement/PilotAgentsDB" , parentLogger = parentLogger )
4651 self ._defaultLogger = self .log
@@ -286,8 +291,9 @@ def getPilotInfo(self, pilotRef=False, conn=False, paramNames=[], pilotID=False)
286291 return S_ERROR (f"Unknown column: { col } " )
287292
288293 cmd = f"SELECT { ', ' .join (parameters )} FROM PilotAgents" # nosec
289- joinSQL = []
290294 tempTables = []
295+ activeKeys = []
296+ result = None
291297 try :
292298 for key , value in [("PilotJobReference" , pilotRef ), ("PilotID" , pilotID )]:
293299 values = []
@@ -310,12 +316,41 @@ def getPilotInfo(self, pilotRef=False, conn=False, paramNames=[], pilotID=False)
310316 insertValues = [(v ,) for v in values ]
311317 returnValueOrRaise (self ._update (sqlCmd , conn = conn ))
312318 tempTables .append (tableName )
313- sqlCmd = f"INSERT INTO { tableName } ({ key } ) VALUES ( %s )" # nosec: B608
314- returnValueOrRaise (self ._updatemany (sqlCmd , insertValues , conn = conn ))
315- joinSQL .append (f"JOIN { tableName } USING ({ key } )" )
316- if joinSQL :
317- cmd = f"{ cmd } { ' ' .join (joinSQL )} "
318- result = self ._query (cmd , conn = conn )
319+ activeKeys .append ((key , tableName , insertValues ))
320+
321+ joinSQL = [f"JOIN { tn } USING ({ k } )" for k , tn , _ in activeKeys ]
322+ selectCmd = f"{ cmd } { ' ' .join (joinSQL )} " if joinSQL else cmd
323+
324+ if not activeKeys :
325+ # No conditions: plain SELECT over the whole table.
326+ result = self ._query (selectCmd , conn = conn )
327+ else :
328+ # Load every condition key fully except the last one, which is
329+ # processed batch by batch (truncating between batches) so the
330+ # in-memory temp table never holds all the rows at once. This
331+ # preserves the AND semantics: the union of the per-batch
332+ # results equals the full JOIN result.
333+ for key , tableName , insertValues in activeKeys [:- 1 ]:
334+ insertCmd = f"INSERT INTO { tableName } ({ key } ) VALUES ( %s )" # nosec: B608
335+ for i in range (0 , len (insertValues ), self .PILOT_INFO_BATCH_SIZE ):
336+ returnValueOrRaise (
337+ self ._updatemany (insertCmd , insertValues [i : i + self .PILOT_INFO_BATCH_SIZE ], conn = conn )
338+ )
339+ batchKey , batchTable , batchValues = activeKeys [- 1 ]
340+ insertCmd = f"INSERT INTO { batchTable } ({ batchKey } ) VALUES ( %s )" # nosec: B608
341+ resultRows = []
342+ for i in range (0 , len (batchValues ), self .PILOT_INFO_BATCH_SIZE ):
343+ returnValueOrRaise (self ._update (f"TRUNCATE TABLE { batchTable } " , conn = conn ))
344+ returnValueOrRaise (
345+ self ._updatemany (insertCmd , batchValues [i : i + self .PILOT_INFO_BATCH_SIZE ], conn = conn )
346+ )
347+ batchResult = self ._query (selectCmd , conn = conn )
348+ if not batchResult ["OK" ]:
349+ result = batchResult
350+ break
351+ resultRows .extend (batchResult ["Value" ])
352+ else :
353+ result = S_OK (resultRows )
319354 finally :
320355 for tableName in tempTables :
321356 sqlCmd = f"DROP TEMPORARY TABLE { tableName } "
0 commit comments