Preliminary Notes About the Generic Querier Application By M. Asherman, 1/13/2000 Intro: The Querier application is a generic table-driven facility for defining canned SELECT - SQL statements. It supports various actions including Run or Count a canned query, with optional application-specific arguments and provision for a flexible interactive parameters dialog. There is also an action, Parms, to test the optional user parameters dialog, without running the rest of the query. The Prompt/PromptR actions allow you to override a query's default destination by using a dialog, optionally with repetition for multiple outputs. The Browse/BrowseN actions allow you to preview results in a browse window, overriding the query's default destination. See querier.prg and querier.h for usage notes. To get a quick overview, start by running the following VFP command: ? querier() This will run the first sample query, which selects the Querier's entire meta-file contents and brings up the generic query output destination dialog. To view the sample query definitions, close the destination dialog and/or Query result window and browse the meta-file (table) that was implicitly opened (alias querydf) by the previous command. As you move the record position in the meta-file, you can run each sample query by issuing the same command, "? querier()", from the VFP command window. See the Notes memo field for each of the samples. You will find it useful to make use of VFP's browse preferences to open up a bunch of memo windows and adjust their sizing and placement, so that BROWSE LAST will restore this arrangement. It's also useful to keep an eye on things through VFP's Data Session window. Note that the querier() function is really just a wrapper for the Querier.QueryCommand method (in querier.vcx). Developers may wish to use the pure class-based interface in order to exercise greater control over the choice of meta-file and data session. To clean up after testing querier() without closing out the current VFP session, use this command: "_screen.removeobject('querier')". This will release the default querier object and close the meta-file. This is mainly useful during development and testing of the Querier facility itself, to avoid "class is in use" errors. Notes about Error Handling Querier() and the corresponding method Querier.QueryCommand() return a logical value, which is a success flag, except for the Count action, which returns a number if successful. When Querier() fails, you can obtain additional error information from properties of the Querier object. The basic Querier application error code and message are always returned in properties Querier.EHP_AppErrCode and EHP_AppErrMsg. Additional generic VFP error information may also be available in properties that start with "EHP_VFPErr" for certain error cases, e.g. errors during processing of the SELECT statement. When property EHP_VFPErrCode is non-zero, there is additional VFP error information available. See querier.h for error code and message macros. Note that the Querier class is based on the generic MDA ErrHandler class (in mdacomm's errhandl.vcx), which will also be used for error handling in other diverse MDA applications. Currently available documentation: - annotated examples are in the sample meta-file, querydf.dbf (see Notes field) - brief descriptions have been attached to all files in querier.pjx - there are DBC-based field comments for all meta-file fields (in querydf.dbf) - note that certain generic mdacomm functions are employed in the meta-file - all programs are liberally commented Related outstanding issues and tasks (* indicates it can wait): - support a diagnostic mode that displays expanded SQL query E.g. to the main VFP window. Nadya requested this on 11/18. Better still, support an optional compiled mode, which generates, compiles, and runs a temporary PRG via the new cmdprg() utility, along the same lines used in xformdbf. - watch out for potential TALK verbosity complications during error handling We expect potential problems because TALK is deliberately turned on during SELECT statement processing. However, maybe having issued an ACTIVATE SCREEN avoids the need for further adjustments. Wait and see what Nancy says about this after she has tested it out. - watch out for cases where user is prompted to replace and says No If output is to a file and user is prompted whether to replace it, and user says No, the query appears to succeed, but in fact it did nothing. This is not a new issue, but maybe behavior should be altered to treat this case as a failre. - tie in VFP's sys(3054) to display Rushmore optimization details This may require additional meta-file field and/or action arg codes. Requires some experimentation to see how to handle this feature. Explicit support of this option may be warranted, because the caller can't separate the parameters dialog step from the running of the query; if caller turns on Rushmore tracing, it may generate unwanted additional tracing for queries internal to the parameters dialog (e.g. btcrit), which will clutter the diagnostic output sent to the main VFP window. However, this does work: by invoking sys(3054,1) before running querier(), you will be able to see useful Rushmore statistics including the main query step. - additional documentation on usage, overall design, and meta-file maintenance - avoid superfluous 2nd prompt for replacement after invoking querdest() - demonstrate how to init btcrit to a template default and assign a new functionid This could be done by supporting some application-specific querier arguments in conjunction with new optional args to btcrit for post-init commands. - optional force into development mode for a user params dialog I.e. illustrate this feature of btcrit, using btcrit's post-init command line arguments. - illustrate tie-in between Reporter and Querier Use of Reporter's initexp to invoke querier() seems to be a sensible way of allowing these apps to be tied together. This may aready work, as-is, but we need to create some good test cases. Not yet tested. *- meta-file field to control SAFETY ON/OFF setting *- generic UDF for opening/closing database (as opposed to table - see usetable.prg) *- support & demonstrate features for chaining or nesting of queries This has some interesting possibilities, for complex multi-step queries. We could use Commandr for multi-step queries, but there may be some benefits to handling some aspects via extensions to querier. Not yet sure about this. Some good examples would help clarify this. *- allow for destination prompt with a pre-defined default file name &/or extension Minor. Something similar is already supported in Reporter. Review this. *- refinement to querdest.scx: support DBF DATABASE and NAME options Minor, but I mention it for completeness. *- meta-file field(s) to control TALK ON/OFF setting and other verbosity options The current implementation provides a high level of verbosity. Options could be added to reduce this, if desired; wait and see. General guidelines and conventions: @- maintain consistent usage notes between wrapper function and corresponding method For this app, that means querier.prg and corresponding Querier.QueryCommand. @- maintain clean copies of selected files in shared mdacomm directory Only copy the app, h, vcx/vct, txt, and any other files that may be directly used by other apps. Don't copy files used only internally within the app. @- maintain thorough error and user escape-handling provisions See querier.h for application-specific error codes and messages. @- avoid unnecessary direct cross-app dependencies by making use of mdacomm @- all apps should avoid potential name conflicts in case moved into mdacomm E.g. avoid file names like "notes.txt" in favor of ".txt". @- add comments in history of each app as to when last uploaded to BT server Change history: 990909 refinements to samples illustrating btcrit() extensions Added new demobt06 example, showing how to obtain the FROM ... JOIN ... clause from btcrit. 990926 regenerate btcrit demo configurations to pick up latest btcrit changes Applies to demobt05 and demobt06. Just ignore initial errors caused by changes to btcrit, which are fixed when configuration is re-opened and saved. 990926 make adjustments for move from M: to D: - adjust icon for launching VFP to start in dir on D:... and use -cd:... option - open .pjx and tell dialog OK to move it from M: to D: 991002 get rid of messagebox in params mode of querier Nancy requested this change on 9/27, because it interferes with intended "setup mode" behavior. 991002 supply example illustrating how to obtain field list from btcrit I worked this into new demobt07, sample slow query. 991002 provide thermometer and other work-in-process indicators Add a new sample query, demobt07, that runs slowly enough to see delays. The previous querier behavior respected the caller's TALK setting, but this is not enough, because forms generally want to keep TALK set OFF. Change querier logic to provide greater verbosity regardless of the current TALK setting. 991002 check for meta-file closed errors For starters, just detect and handle this error cleanly. Maybe should just re-open it automatically in these cases, using new property for saved meta-file path, but this is not yet done. 991003 add block of comments summarizing supported action codes in querier.prg 991003 demonstrate interactive/non-interactive modes of invoking user params dialog I.e. illustrate this feature of btcrit, using btcrit's action argument. I worked this into the slow query example, demobt07. This illustrates how to use optional user-defined Querier() arguments. 991004 revised sample demobt07 to be a little faster on the BT server machine This change was applied manually on the BT server, after delivering and testing updates (prior to this change) this morning. 991004 **** UPLOADED CHANGES TO BT SERVER'S D:\REDP\APPL\QUERIER\ & ...MDACOMM\ **** 991029 query thermometer/TALK garbles Nancy's Query form - try to fix this Try using ACTIVATE SCREEN right before the query, for starters. We need to use SET TALK ON during query processing in order to get the benefit of VFP's builtin query progress indicators. Since I can't easily reproduce the problem, let Nancy test this change to see if the fix works. 991029 updated btcrit configurations used by sample querier meta-file 991029 **** UPLOADED CHANGES TO BT SERVER'S D:\REDP\APPL\QUERIER\ & ...MDACOMM\ **** 991103 fix bug allowing invalid action args to go undetected E.g. an action of "prompthahaha" is treated as equivalent to "prompt" - oops! The old SET EXACT hassle strikes again! 991103 add querier properties for returning error status information And be sure all return cases from Querier.QueryCommand set these properties appropriately. Add new property for error code, qryp_ercode, and new property for expanded error message, qryp_ermsg. 991104 provide distinct error codes and messages for each failure case Defined in querier.h. 991104 suppress pausing on errors for non-interactive cases Compare with recent changes to xformdbf, where we introduced a new method, XFormDBF.XFOM_ErrMsg, for handling error messages. Introduce new property, qryp_interactive, which is initialized by QueryCommand method. Non-interactive queries must have action = Run or Count. 991104 let cleanupexp failure be treated as a normal error Previously, the failure of cleanupexp was not regarded as a failure of the query. Change logic to check for and report any such errors, unless superseded by a previous error.rather than allowing them to go unnoticed. 991104 support clean escape-handling during query execution Compare with similar logic in XFormDBF.XFOM_Run. 991106 introduce new generic error-handling class, ErrHandler, suitable for querier I looked at VFP's FFC _error class, and also some examples of error-handling logic used by Doug Hennig, based on Stonefield's framework. Neither of those approaches is simple enough nor are they adequately documented and commented for me to feel comfortable with them. So I created a simple, modular, custom ErrHandler class in mdacomm\errhandl.vcx, which I will use for diverse MDA apps. 991106 fix error reporting method qrym_ermsg to handle long messages Avoid errors due to WAIT WINDOW limitations. We could make use of messagebox() to increase the max length limit for interactive cases. Non-interactive cases should just truncate and end in "...". 991107 better error detection and handling during the SELECT statement We also want to handle other contexts as well, where explicit error checks are not practical, but the initial focus is just the processing of the macro-expanded SELECT statement. The same approach can be carried to other contexts as the need arises. 991107 shift error reporting method from Querier into generic ErrHandler With a little adjustment we should be able to turn this into a generic piece of logic, thereby leveraging this feature across all ErrHandler subclasses. Also eliminate obsolete error-related properties we added to Querier, since these are now replaced by ErrHandler properties. 991107 include VFP error info captured via program() and sys(16) 991107 add blank lines between sections of long error messages For better readability and easier distinction between app-specific and generic VFP parts. 991107 supply a title for messagebox error reporting cases I guess a reasonable default would display the methodname and the application-specific error #. Custom property(ies) could be used to override this, e.g. to substitute "Querier" or "Querier.QueryCommand" for the default of "Querycommand". Try this: introduce new ehp_appname property, which picks up method name as the default. We may as well always display the application-specific error # in the window title, since we don't display it elsewhere. 991107 allow for a default prefix to be added to WAIT WINDOW messages I.e. provide ErrHandler property(ies) to do this automatically, as an option, just as there is some way of constructing a default messagebox title. 991107 may as well throw in an option as to type of messagebox to be used Based on new property, ErrHandler.ehp_messageboxtype. 991107 avoid needless discrepancy between SELECT errors in loop vs final one 991107 include clearing of status bar text in ErrHandler.ehp_apperrcode logic This would eliminate the need for lots of scattered SET MESSAGE TO commands that usually follow error messages. Double-check that this is always ok - seems ok for all current querier usage. Remove redundant SET MESSAGE TO commands from querier.querycommand method. We could add a property to ErrHandler to make this behavior optional if necessary, but wait and see if needed. 991107 add a querier property, qryp_tally, for holding on to final _tally To avoid risk of losing this value because of some later action that alters the _tally system memory variable. 991108 add a global mvar, m.qry_querier, pointing to the Querier object itself As a convenience, e.g. for getting to error information and any other Querier properties. The same idea should also be carried to other MDA apps. 991108 add a global mvar for easy reference to the current query_id Review Commander logic for refinements that were made after the initial Reporter implementation. Since querier was adapted from Reporter, I missed picking up a few small refinements that were made in Commander, which was done after Reporter. 991108 automatically open meta-file in Querier.QueryCommand if necessary Normally this should always be open, but may as well just auto-open if it has been closed, e.g. via CLOSE ALL. Add a new form property to keep track of meta-file path (saved in Init method). Compare with recent similar change to Commander. Introduce new property, querier.qryp_metafile, for holding on to the full meta-file path and filename. Also add new method, qrym_open, to handle the logic for opening the meta-file. 991108 display value of usrparmexp on failure due to Escape from parameters dialog 991108 if destination dialog is used, always treat as an interactive invocation I.e. let error messages be displayed with a pause (e.g. via messagebox) in these cases, to give the user the best chance of seeing error info. 991108 **** UPLOADED CHANGES TO BT SERVER'S D:\REDP\APPL\QUERIER\ & ...MDACOMM\ **** 991203 rebuild and test Querier after changes to foundation ErrHandler class 991203 **** UPLOADED CHANGES TO BT SERVER'S D:\REDP\APPL\QUERIER\ & ...MDACOMM\ ****