Estimados,
A menudo necesito datos de diferentes fuentes y los combino. Como algunas consultas pueden llevar mucho tiempo, escribí un script para iniciar varias consultas en segundo plano y combinar datos al final. Sin embargo, no es tan fácil encontrar el desencadenante, cuándo se han terminado todas las consultas y cuándo comenzar a procesar los resultados. En el siguiente script, probé dos enfoques (Establecer el indicador por "OnRunComplete" y probar la existencia de la tabla de resultados). Funcionan bastante, pero creo que puede haber incluso una mejor manera.
Un problema es que el bucle se ejecutará infinitamente si una de las consultas no entrega ninguna tabla. Otro problema es que el script no controla realmente si las consultas aún están activas.
El script está configurado actualmente en un modo de depuración, donde no es necesaria una conexión a la base de datos para probar este comportamiento.
¿Alguna idea para mejorar? gracias y BR
// Purpose:
// Start two database Queries (from different sources) in parallel and in background
// Wait for queries to finish
// and combine result
// JMP 15.0 Win10
//
// Details:
// After both queries are started in background
// a loop is started, that queries when both tables are existing
// In a previous version I worked with setting a flag ("OnRunComplete( B_QUERY_FINISHED = 1 )")
//
// Problem:
// A better solution would be to test, whether DB query is still running, but how?
// If the database query ends unexpectedly (by passing no table), the loop runs infinetely
Names Default To Here( 1 );
Clear Log();
// debug_mode: 0 - query from database / 1 - make table
// for database query the connectionstring must be correct
debug_mode = 1;
A_QUERY_FINISHED = 0;
B_QUERY_FINISHED = 0;
A_NAME = "A_Table";
B_NAME = "B_Table";
// new function to check whether background query is finished (= table does exists)
table_exists = Function( {table_name},
Names Default To Here( 1 );
table_lst = Get Data Table List();
table_name_lst = {};
For( i = 1, i <= N Items( table_lst ), i++,
Insert Into( table_name_lst, table_lst[i] << get name() )
);
Return( If( Contains( table_name_lst, table_name ) > 0, 1, 0 ) );
);
If( table_exists( A_NAME ) | table_exists( B_NAME ) ,
Throw( eval insert ("^A_NAME^ or ^B_NAME^ open! Please close " ))
);
// Define query
sql_str = "Select * from dual";
A_sql_str = sql_str;
B_sql_str = Substitute( sql_str, "A_scheme", "B_scheme" );
// Database query expression in backgroud
nsqlq_A_expr = Expr(
New SQL Query( Connection( "ODBC:DSN=XXX;DBQ=YYY;" ), QueryName( A_Name ), CustomSQL( A_sql_str ) ) <<
Run Background( OnRunComplete( A_QUERY_FINISHED = 1 ) )
);
nsqlq_B_expr = Expr(
New SQL Query( Connection( "ODBC:DSN=ZZZ;DBQ=AAA;" ), QueryName( B_Name ), CustomSQL( B_sql_str ) ) <<
Run Background( OnRunComplete( B_QUERY_FINISHED = 1 ) )
);
// Create table expression for Debugging
A_expr = Expr(
New Table( "A_Table", Add Rows( 1 ), Compress File When Saved( 1 ), New Column( "DUMMY", Character, "Nominal", Set Values( {"X"} ) ) )
);
B_expr = Expr(
New Table( "B_Table", Add Rows( 1 ), Compress File When Saved( 1 ), New Column( "DUMMY", Character, "Nominal", Set Values( {"X"} ) ) )
);
// start queries only in case of no debug_mode
If( debug_mode == 0,
Eval( nsqlq_A_expr );
Eval( nsqlq_B_expr );
);
start_time = Tick Seconds();
timestep = 1;
While( (table_exists( A_NAME ) & table_exists( B_NAME )) != 1,
Wait( timestep );
time_running = Round( Tick Seconds() - start_time, 0 );
Print( "waiting " || Char( time_running ) );
Show( table_exists( A_NAME ) );
Show( table_exists( B_NAME ) );
// For debugging only: create Table A after 5 seconds and Table B after 10 seconds
If( debug_mode == 1,
If( time_running > 5 & !table_exists( A_NAME ),
Eval( A_expr )
);
If( time_running > 10 & !table_exists( B_NAME ),
Eval( B_expr )
);
);
);
Wait( 1 );
Print( "Queries Finished" );
end_time = Tick Seconds();
Print( "Duration: " || Char( Round( end_time - start_time ) ) );
// concatenate
Try( Data Table( A_Name ) << Concatenate( Data Table( B_Name ), Append to first table ), Throw( Print( "Concatenate error" ) ) );
// Close( Data Table( B_Name ), nosave );
Data Table( A_Name )<< set name("Result Table");
Print( "Concatenating finished, script end " );No creo que haya experimentado este mismo problema, si continúa teniendo problemas, ¿puede publicar el resultado del registro con el error, o si puede solucionarlo, puede decirme cómo puedo actualizar el script de ejemplo?
Hay una configuración de ODBC en las preferencias que me ha llevado a un mal comportamiento similar. Si la opción "Ejecutar consultas en segundo plano si es posible" está marcada, desmárquela e intente su secuencia de comandos nuevamente. Creo que hay una compensación de velocidad por estabilidad al hacer esto, pero vale la pena experimentar si aún no lo has hecho.

Gracias @ih para su solución, es agradable y está bien programada, así que intentaré trabajar con ella.
En una primera prueba, todavía vi algunos problemas de tiempo (supongo), porque una referencia (todavía no) era válida.
Introducir una espera de varios segundos en la Declaración "onRunComplete" funcionó, pero no es la solución.
Creo que es por eso que antes decidí consultar las tablas disponibles antes de hacer referencia a ellas. Lo probaré más.