Exécutez des requêtes en arrière-plan, attendez qu'elles se terminent et référencez-les dans le script JSL restantProblème
Vous souhaitez exécuter une requête en arrière-plan afin que l'interface utilisateur ne se fige pas, ou vous souhaitez exécuter plusieurs requêtes en même temps, puis combiner les résultats. Parfois, il est difficile de mettre toutes les fonctionnalités dont vous avez besoin dans le script « à l'exécution terminée » des requêtes en arrière-plan.
Solution
Chaque requête enregistre les résultats dans un nouvel espace de noms auquel tous les scripts peuvent accéder (requêtes et script d'origine).Le script d'origine continue de vérifier les résultats avant de continuer.
//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 );Vous souhaitez exécuter des requêtes en arrière-plan mais devez interagir avec les résultats.Cette méthode permet de terminer plusieurs requêtes en arrière-plan avant d'interagir avec les résultats.
UtilitairesRe : Exécuter des requêtes en arrière-plan, attendre qu'elles se terminent et référencer-les dans le script JSL restantBonjour @MarkDayton ,
Merci d'avoir creusé ce sujet car vous avez souligné une lacune du script que je viens de corriger. Je n'avais pas de noms par défaut ici (1) dans les scripts OnRunComplete, donc cela ne fonctionnait pas exactement comme je l'avais prévu.Voici une description des espaces de noms avant et après la mise à jour. juste fait:
Aperçu
Notez comment l'espace de noms « requêtes » est créé dans le script parent, puis référencé dans les scripts OnRunComplete.La variable ns elle-même n'est utilisée que pour référencer les « requêtes » de l'espace de noms.Par exemple, dans une nouvelle fenêtre de script, vous pouvez exécuter :
Names default to here(1);
ns = New Namespace("queries");
ns:a = 1
et une deuxième fenêtre de script pourrait obtenir la valeur de a en appelant :
Names default to here(1);
Show(Namespace("queries"):a);
mais vous ne pouvez pas facilement accéder à ns dans l'autre fenêtre. Vous pouvez cependant définir une nouvelle variable dans l'autre fenêtre, puis accéder à une de manière similaire :
Names default to here(1);
nsreference = Namespace("queries");
Show(nsreference);
Ou, pour rendre le code plus facile à lire, vous pouvez utiliser le même nom de variable dans les deux fenêtres.Les variables elles-mêmes sont différentes car elles sont définies dans des espaces de noms différents, mais elles font référence à la même chose et vous pouvez donc les utiliser de la même manière.
Names default to here(1);
ns = Namespace("queries");
Show(ns:a);
Voici comment les variables sont utilisées dans l'exemple de script ci-dessus : une variable appelée "ns" est créée dans chaque espace de noms ici qui fait référence à l'espace de noms nommé "requêtes", ce qui facilite le partage de valeurs entre ces scripts.
Avant le changement - comment cela fonctionnerait sans démarrer chaque script OnRunComplete avec les noms par défaut ici (1) :
Voir plus...
Après le changement - comment fonctionne le script maintenant
Quatre espaces de noms sont utilisés par le script :
- L'espace de noms ici pour la fenêtre de script parent
- L'espace de noms ici pour le script OnRunComplete de la première requête
- L'espace de noms ici pour le script OnRunComplete de la deuxième requête
- L'espace de noms nommé « requêtes », référencé à la fois par le script parent et par les deux scripts OnRunComplete
La variable ns dans le script parent est définie dans l'espace de nom ici pour référence l'espace de noms des requêtes, qui est créé avec New Namespace().Cela signifie que seule la fenêtre de script a accès à ns, mais tout le reste dans cette instance de JMP peut faire référence à tout ce qui est enregistré dans l'espace de noms des requêtes référencé par ns.
Les scripts OnRunComplete sont ouverts dans un nouvel environnement et n'ont pas accès à l'espace de noms ici du script parent.Ainsi, une nouvelle variable également appelée ns est définie dans l'espace de noms ici de ce script, et elle est définie pour référencer l'espace de noms « requêtes » à l'aide de Namespace().Chaque script d'exécution complète crée sa propre variable appelée ns dans son propre espace de noms ici, mais chacune d'entre elles sera ensuite définie pour référencer le même espace de noms « requêtes ».
Re : Exécuter des requêtes en arrière-plan, attendre qu'elles se terminent et référencer-les dans le script JSL restantTout d'abord, merci pour ce script. Utilisation d'espaces de noms, script de requêtes SQL, test si elles sont terminées, fournir un retour d'information sur l'état, gérer les résultats ; ce script regroupe de nombreux enseignements dans quelques lignes de JSL.Je peux en suivre la majeure partie, mais Je n'ai pas beaucoup d'expérience dans la définition et l'utilisation des espaces de noms, j'ai donc une question :
Dans la deuxième ligne du script, ns est défini comme :
ns = new namespace( "queries" );
Il semble alors ns est redéfini dans les instructions Run Background() :
sql_query2 << Run Background( OnRunComplete(
ns = namespace( "queries" );
ns:dt2 = queryResult;
ns:query2isdone = 1;
) );
L'espace de noms dans sql_query1 & 2 est-il le même espace de noms que celui défini au début du script, il semble que ce devrait être le cas, ou s'agit-il d'un espace de noms local à l'instruction de requête en raison de la Noms par défaut ici (1) déclaration au début ? Pourquoi ns doit-il être défini dans l'instruction Run Background() ?
Merci encore pour ce morceau de code simple, clair et magnifique.
Re : Exécuter des requêtes en arrière-plan, attendre qu'elles se terminent et référencer-les dans le script JSL restantquand même, un bon bout de code à référencer dans un endroit difficile. : )
Re : Exécuter des requêtes en arrière-plan, attendre qu'elles se terminent et référencer-les dans le script JSL restantSalut @Byron_JMP ,
Je suis d'accord si l'objectif est de vérifier l'état des requêtes exécutées de manière interactive, alors un utilisateur ne devrait pas chercher plus loin que le générateur de requêtes.Cette fenêtre d'état était destinée à démontrer les parties du travail avec des requêtes que les utilisateurs avaient du mal à trouver avec de simples recherches sur le Web, comme le référencement des résultats dans un script une fois celui-ci terminé. Pour être honnête, je me souviens avoir eu du mal à trouver un exemple minimal.Je suis sûr qu'il existe un meilleur cas d'utilisation...
Re : Exécuter des requêtes en arrière-plan, attendre qu'elles se terminent et référencer-les dans le script JSL restantcela ressemble à une idée de projet vraiment intrigante.
Je voulais juste noter que dans Query Builder, il existe un onglet de progression où je peux voir combien de requêtes sont en cours d'exécution et leur progression. Peut-être que ce serait un moyen de créer un script pour la plate-forme de création de requêtes pour afficher ces informations plutôt que d'essayer de les obtenir à partir de zéro ?