Carissimi,
Spesso ho bisogno di dati provenienti da fonti diverse e li combino. Poiché alcune query potrebbero richiedere molto tempo, ho scritto uno script per avviare diverse query in Background e combinare i dati alla fine. Tuttavia, non è così facile trovare il trigger, quando tutte le query sono state completate e quando iniziare l'elaborazione dei risultati. Nello script seguente ho testato due approcci (impostazione del flag tramite "OnRunComplete" e test dell'esistenza della tabella dei risultati). Funzionano abbastanza, ma penso che possa esserci un modo ancora migliore.
Un problema è che il ciclo verrà eseguito all'infinito se una delle query non fornisce alcuna tabella. Un altro problema è che lo script non controlla realmente se le query sono ancora attive.
Lo script è attualmente impostato in modalità debug, in cui non è necessaria alcuna connessione al database per testare questo comportamento.
Qualche idea per migliorare? Grazie e 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 " );Non credo di aver riscontrato lo stesso problema, se continui ad avere problemi puoi pubblicare l'output del registro con l'errore o, se riesci a risolverlo, puoi farmi sapere come posso aggiornare lo script di esempio?
C'è un'impostazione ODBC nelle preferenze che mi ha portato a comportamenti scorretti simili. Se l'opzione "Esegui query in background, se possibile" è selezionata, deselezionala e riprova lo script. Penso che ci sia un compromesso tra velocità e stabilità nel fare questo, ma vale la pena sperimentarlo se non l'hai già fatto.

Grazie @ih per la tua soluzione, è carina e ben programmata, quindi proverò a lavorarci.
In un primo test ho riscontrato ancora qualche problema di Timing (suppongo), perché un riferimento era (non ancora) valido.
L'introduzione di un'attesa di diversi secondi nell'istruzione "onRunComplete" ha funzionato, ma non è la soluzione.
Penso che sia per questo che in precedenza ho deciso di interrogare le tabelle disponibili prima di farvi riferimento. Lo testerò ulteriormente.