Ejecute consultas en segundo plano, espere a que se completen y haga referencia a ellas en el script JSL restante.Problema
Quiere ejecutar una consulta en segundo plano para que la interfaz de usuario no se congele, o desea ejecutar varias consultas al mismo tiempo y luego combinar los resultados. A veces es difícil poner todas las funciones que necesita en el script "en ejecución completa" de las consultas en segundo plano.
Solución
Cada consulta guarda los resultados en un nuevo espacio de nombres al que pueden acceder todos los scripts (consultas y el script original).El script original sigue comprobando los resultados antes de continuar.
//Example script which runs queries in the background and references their results
//once finished.
Names default to here(1);
// Namespace to share data between background query and this script
ns = new namespace( "queries" );
// Flags which the background query will set to 1 when the background query is complete
ns:query1isdone = 0;
ns:query2isdone = 0;
// Open a window to display results
win = New window("Query Status", show menu(0), show toolbars(0),
text box("Status of queries:"),
tb = tablebox( string col box( "Query" , { "Query 1", "Query 2" } ),
string col box( "Status", { "Not Started", "Not Started" } ) ),
tbStatus = text box("Starting queries.")
);
wait(0); //make sure window shows up
// Define and start background queries
// First Query
sql_query1 = New SQL Query(
Connection( "ODBC:DSN=Test Source;DATABASE=Test Database;" ),
QueryName( "Query" ),
Select( vars ),
From( table ),
Where( condition )
);
sql_query1 << Run Background( OnRunComplete(
Names default to here(1);<BR /> ns = namespace( "queries" );
ns:dt1 = queryResult;
ns:query1isdone = 1;
) );
// Second Query
sql_query2 = New SQL Query(
Connection( "ODBC:DSN=Test Source;DATABASE=Test Database;" ),
QueryName( "Query" ),
Select( vars ),
From( table ),
Where( condition )
);
sql_query2 << Run Background( OnRunComplete(
Names default to here(1);<BR /> ns = namespace( "queries" );
ns:dt2 = queryResult;
ns:query2isdone = 1;
) );
// Every second check if the query is done (timeout after 10 seconds)
i=0;
allqueriesdone = 0;
starttime = tick seconds();
while( ( i < 10 ) & allqueriesdone == 0 ,
i++;
wait(1);
if( ns:query1isdone == 1,
tb << delete row( 1 );
tb << insert row( 1, {"Query 1", "Complete"} );,
tb << delete row( 1 );
tb << insert row( 1, {"Query 1", "Still Running"} );
);
if( ns:query2isdone == 1,
tb << delete row( 2 );
tb << insert row( 2, {"Query 2", "Complete"} );,
tb << delete row( 2 );
tb << insert row( 2, {"Query 2", "Still Running"} );
);
if( (ns:query1isdone == 1 ) & (ns:query2isdone == 1 ), allqueriesdone = 1 ); //indicate that everything finished
tbStatus << Set Text( "Queries are running, " || format(tick seconds() - starttime, "Fixed Dec", 12, 1) || " seconds elapsed." );
win << bring window to front;
);
// Show an error if any queries didn't finish
if( allqueriesdone == 0,
tbStatus << Set Text("Error, a query didn't finish and is still running!"),
tbStatus << Set Text("Queries finished after " || format(tick seconds() - starttime, "Fixed Dec", 12, 1) || " seconds.");
//win << Close Window; //could close window here
);
// Now reference the data tables
show( ns:dt1 );
show( ns:dt2 );Quiere ejecutar consultas en segundo plano pero necesita interactuar con los resultados.Este método permite completar múltiples consultas en segundo plano antes de interactuar con los resultados.
UtilidadesRe: Ejecutar consultas en segundo plano, esperar a que se completen y hacer referencia a ellas en el script JSL restanteHola @MarkDayton ,
Gracias por profundizar en esto ya que señaló un defecto del guión que acabo de corregir. No tenía los nombres predeterminados aquí (1) en los scripts de OnRunComplete, por lo que no estaba funcionando exactamente como lo planeé.Aquí hay una descripción de los espacios de nombres antes y después de la actualización. justo hecho:
Descripción general
Observe cómo es el espacio de nombres 'consultas' creado en el script principal y luego referenciado en los scripts OnRunComplete.La variable ns en sí solo se usa para hacer referencia a las 'consultas' del espacio de nombres.Por ejemplo, en una nueva ventana de script podría ejecutar:
Names default to here(1);
ns = New Namespace("queries");
ns:a = 1
y una segunda ventana de script podría obtener el valor de a llamando a:
Names default to here(1);
Show(Namespace("queries"):a);
pero no puedes acceder fácilmente a ns en la otra ventana. Sin embargo, puede definir una nueva variable en la otra ventana y luego acceder a ella de manera similar:
Names default to here(1);
nsreference = Namespace("queries");
Show(nsreference);
O, para que el código sea más fácil de leer, puede utilizar el mismo nombre de variable en ambas ventanas.Las variables en sí son diferentes ya que están definidas en diferentes espacios de nombres, pero hacen referencia a lo mismo para que puedas usarlas de la misma manera.
Names default to here(1);
ns = Namespace("queries");
Show(ns:a);
Así es como se usan las variables en el script de ejemplo anterior: se crea una variable llamada 'ns' en cada espacio de nombres aquí que hace referencia a las 'consultas' del espacio de nombres nombrado, lo que facilita compartir valores entre esos scripts.
Antes del cambio - cómo funcionaría esto sin iniciar cada script OnRunComplete con los nombres predeterminados aquí (1):
Ver más...
Después del cambio - cómo funciona el guión ahora
El script utiliza cuatro espacios de nombres:
- El espacio de nombres aquí para la ventana del script principal.
- El espacio de nombres aquí para el script OnRunComplete de la primera consulta.
- El espacio de nombres aquí para el script OnRunComplete de la segunda consulta.
- El espacio de nombres llamado 'consultas', al que hacen referencia tanto el script principal como los dos scripts OnRunComplete
La variable ns en el script principal se define en el espacio de nombres aquí para referencia el espacio de nombres de consultas, que se crea con New Namespace().Eso significa que solo la ventana del script tiene acceso a ns, pero cualquier otra cosa en esa instancia de JMP puede hacer referencia a lo que esté guardado dentro del espacio de nombres de consultas al que hace referencia ns.
Los scripts OnRunComplete se abren en un nuevo entorno y no tienen acceso al espacio de nombres aquí del script principal.Por lo tanto, una nueva variable que también se llama ns se define en el espacio de nombres aquí de ese script y se configura para hacer referencia al espacio de nombres 'consultas' usando Namespace().Cada script de ejecución completa crea su propia variable llamada ns en su propio espacio de nombres aquí, pero luego cada uno de ellos se configurará para hacer referencia al mismo espacio de nombres de "consultas".
Re: Ejecutar consultas en segundo plano, esperar a que se completen y hacer referencia a ellas en el script JSL restantePrimero, gracias por este guión. Uso de espacios de nombres, secuencias de comandos de consultas SQL, pruebas de si están terminadas, proporcionar retroalimentación sobre el estado, gestionar los resultados; Este script incluye mucha enseñanza en unas pocas líneas de JSL.Puedo seguir la mayor parte, pero No tengo mucha experiencia definiendo y usando espacios de nombres, así que tengo una pregunta:
En la segunda línea del guión, ns es definido como :
ns = new namespace( "queries" );
Entonces parece ns se redefine en las sentencias Run Background():
sql_query2 << Run Background( OnRunComplete(
ns = namespace( "queries" );
ns:dt2 = queryResult;
ns:query2isdone = 1;
) );
¿El espacio de nombres dentro de sql_query1 y 2 es el mismo espacio de nombres que el definido al principio del script? Parece que tendría que serlo, o es un espacio de nombres que es local a la declaración de consulta debido a la Nombres predeterminados aquí (1) declaración al principio? Por que ns ¿Necesita definirse dentro de la instrucción Run Background()?
Gracias de nuevo por un código simple, claro y hermoso.
Re: Ejecutar consultas en segundo plano, esperar a que se completen y hacer referencia a ellas en el script JSL restanteaún así, un buen fragmento de código al que hacer referencia en una situación difícil. : )
Re: Ejecutar consultas en segundo plano, esperar a que se completen y hacer referencia a ellas en el script JSL restanteHola @Byron_JMP ,
Estoy de acuerdo, si el objetivo es verificar el estado de las consultas ejecutadas de forma interactiva, entonces el usuario no debería buscar más allá del Generador de consultas.Esta ventana de estado estaba destinada a demostrar las partes del trabajo con consultas que los usuarios tenían problemas para encontrar con búsquedas web simples, como hacer referencia a los resultados en un script una vez completado. Para ser honesto, recuerdo que me costó encontrar un ejemplo mínimo.Estoy seguro de que existe un mejor caso de uso...
Re: Ejecutar consultas en segundo plano, esperar a que se completen y hacer referencia a ellas en el script JSL restanteEsto suena como una idea de proyecto realmente intrigante.
Solo quería señalar que en Query Builder hay una pestaña de progreso donde puedo ver cuántas consultas se están ejecutando y su progreso. ¿Quizás esta sería una forma de programar la plataforma del generador de consultas para mostrar esta información en lugar de intentar obtenerla desde cero?