1 /**
  2  * @fileOverview
  3  * @author <a href="https://www.labkey.org">LabKey</a> (<a href="mailto:info@labkey.com">info@labkey.com</a>)
  4  * @license Copyright (c) 2008-2018 LabKey Corporation
  5  * <p/>
  6  * Licensed under the Apache License, Version 2.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at
  9  * <p/>
 10  * http://www.apache.org/licenses/LICENSE-2.0
 11  * <p/>
 12  * Unless required by applicable law or agreed to in writing, software
 13  * distributed under the License is distributed on an "AS IS" BASIS,
 14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  * See the License for the specific language governing permissions and
 16  * limitations under the License.
 17  * <p/>
 18  */
 19 
 20 /**
 21  * @namespace Query static class to programmatically retrieve, insert, update and
 22  *		delete data from LabKey public queries. <p/>
 23  *		{@link LABKEY.Query.selectRows} works for all LabKey public queries.  However,
 24  *		{@link LABKEY.Query.updateRows}, {@link LABKEY.Query.insertRows} and
 25  *		{@link LABKEY.Query.deleteRows} are not available for all tables and queries.
 26  *            <p>Additional Documentation:
 27  *              <ul>
 28  *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=labkeySql">
 29  *                      LabKey SQL Reference</a></li>
 30  *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
 31  *                      How To Find schemaName, queryName & viewName</a></li>
 32  *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=javascriptTutorial">LabKey JavaScript API Tutorial</a> and
 33  *                      <a href="https://www.labkey.org/home/Study/demo/wiki-page.view?name=reagentRequest">Demo</a></li>
 34  *              </ul>
 35  *           </p>
 36  */
 37 LABKEY.Query = new function()
 38 {
 39     function sendJsonQueryRequest(config)
 40     {
 41         var dataObject = {
 42             schemaName : config.schemaName,
 43             queryName : config.queryName,
 44             rows : config.rows || config.rowDataArray,
 45             transacted : config.transacted,
 46             extraContext : config.extraContext
 47         };
 48 
 49         var requestConfig = {
 50             url : LABKEY.ActionURL.buildURL("query", config.action, config.containerPath),
 51             method : 'POST',
 52             success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope),
 53             failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
 54             jsonData : dataObject,
 55             headers : {
 56                 'Content-Type' : 'application/json'
 57             }
 58         };
 59 
 60         if (LABKEY.Utils.isDefined(config.timeout))
 61             requestConfig.timeout = config.timeout;
 62 
 63         return LABKEY.Ajax.request(requestConfig);
 64     }
 65 
 66     function getSuccessCallbackWrapper(callbackFn, stripHiddenCols, scope, requiredVersion)
 67     {
 68         if (requiredVersion && (requiredVersion === 13.2 || requiredVersion === "13.2" || requiredVersion === 16.2 || requiredVersion === 17.1)) {
 69             return LABKEY.Utils.getCallbackWrapper(function(data, response, options){
 70                 if (data && callbackFn)
 71                     callbackFn.call(scope || this, new LABKEY.Query.Response(data), response, options);
 72             }, this);
 73         }
 74 
 75         return LABKEY.Utils.getCallbackWrapper(function(data, response, options){
 76             if (data && data.rows && stripHiddenCols)
 77                 stripHiddenColData(data);
 78             if (callbackFn)
 79                 callbackFn.call(scope || this, data, options, response);
 80         }, this);
 81     }
 82 
 83     function stripHiddenColData(data)
 84     {
 85         //gather the set of hidden columns
 86         var hiddenCols = [];
 87         var newColModel = [];
 88         var newMetaFields = [];
 89         var colModel = data.columnModel;
 90         for(var idx = 0; idx < colModel.length; ++idx)
 91         {
 92             if (colModel[idx].hidden)
 93                 hiddenCols.push(colModel[idx].dataIndex);
 94             else
 95             {
 96                 newColModel.push(colModel[idx]);
 97                 newMetaFields.push(data.metaData.fields[idx]);
 98             }
 99         }
100 
101         //reset the columnModel and metaData.fields to include only the non-hidden items
102         data.columnModel = newColModel;
103         data.metaData.fields = newMetaFields;
104 
105         //delete column values for any columns in the hiddenCols array
106         var row;
107         for(idx = 0; idx < data.rows.length; ++idx)
108         {
109             row = data.rows[idx];
110             for(var idxHidden = 0; idxHidden < hiddenCols.length; ++idxHidden)
111             {
112                 delete row[hiddenCols[idxHidden]];
113                 delete row[LABKEY.Query.URL_COLUMN_PREFIX + hiddenCols[idxHidden]];
114             }
115         }
116     }
117 
118     function configFromArgs(args)
119     {
120         return {
121             schemaName: args[0],
122             queryName: args[1],
123             rows: args[2],
124             successCallback: args[3],
125             errorCallback: args[4]
126         };
127     }
128 
129     function getMethod(value)
130     {
131         if (value && (value.toUpperCase() === 'GET' || value.toUpperCase() === 'POST'))
132             return value.toUpperCase();
133         return 'GET';
134     }
135 
136     // public methods:
137     /** @scope LABKEY.Query */
138     return {
139 
140         /**
141          * An enumeration of the various container filters available. Note that not all
142          * data types and queries can contain that spans multiple containers. In those cases,
143          * all values will behave the same as current and show only data in the current container. 
144          * The options are as follows:
145          * <ul>
146          * <li><b>current:</b> Include the current folder only</li>
147          * <li><b>currentAndFirstChildren:</b> Include the current folder and all first children, excluding workbooks</li>
148          * <li><b>currentAndSubfolders:</b> Include the current folder and all subfolders</li>
149          * <li><b>currentPlusProject:</b> Include the current folder and the project that contains it</li>
150          * <li><b>currentAndParents:</b> Include the current folder and its parent folders</li>
151          * <li><b>currentPlusProjectAndShared:</b> Include the current folder plus its project plus any shared folders</li>
152          * <li><b>allFolders:</b> Include all folders for which the user has read permission</li>
153          * </ul>
154          */
155         containerFilter : {
156             current: "Current",
157             currentAndFirstChildren: "CurrentAndFirstChildren",
158             currentAndSubfolders: "CurrentAndSubfolders",
159             currentPlusProject: "CurrentPlusProject",
160             currentAndParents: "CurrentAndParents",
161             currentPlusProjectAndShared: "CurrentPlusProjectAndShared",
162             allFolders: "AllFolders"
163         },
164 
165         /**
166          * Execute arbitrary LabKey SQL. For more information, see the
167          * <a href="https://www.labkey.org/Documentation/wiki-page.view?name=labkeySql">
168          * LabKey SQL Reference</a>.
169          * @param config An object which contains the following configuration properties.
170          * @param {String} config.schemaName name of the schema to query.
171          * @param {String} config.sql The LabKey SQL to execute.
172          * @param {String} [config.containerPath] The path to the container in which the schema and query are defined,
173          *       if different than the current container. If not supplied, the current container's path will be used.
174          * @param {String} [config.containerFilter] One of the values of {@link LABKEY.Query.containerFilter} that sets
175          *       the scope of this query. Defaults to containerFilter.current, and is interpreted relative to
176          *       config.containerPath.
177          * @param {Function} config.success
178                  Function called when the "selectRows" function executes successfully.
179                  This function will be called with the following arguments:
180                  <ul>
181                      <li>
182                          <b>data:</b> If config.requiredVersion is not set, or set to "8.3", the success handler will be
183                          passed a {@link LABKEY.Query.SelectRowsResults} object. If set to "9.1" the success handler will
184                          be passed a {@link LABKEY.Query.ExtendedSelectRowsResults} object. If requiredVersion is greater than 13.2 the success
185                          handler will be passed a {@link LABKEY.Query.Response} object.
186                      </li>
187                      <li><b>responseObj:</b> The XMLHttpResponseObject instance used to make the AJAX request</li>
188                      <li><b>options:</b> The options used for the AJAX request</li>
189                  </ul>
190          * @param {Function} [config.failure] Function called when execution of the "executeSql" function fails.
191          *                   See {@link LABKEY.Query.selectRows} for more information on the parameters passed to this function.
192          * @param {Integer} [config.maxRows] The maximum number of rows to return from the server (defaults to returning 100,000 rows).
193          * @param {Integer} [config.offset] The index of the first row to return from the server (defaults to 0).
194          *        Use this along with the maxRows config property to request pages of data.
195          * @param {Boolean} [config.includeTotalCount] Include the total number of rows available (defaults to true).
196          *       If false totalCount will equal number of rows returned (equal to maxRows unless maxRows == 0).
197          * @param {String} [config.sort] A sort specification to apply over the rows returned by the SQL. In general,
198          * you should either include an ORDER BY clause in your SQL, or specific a sort specification in this config property,
199          * but not both. The value of this property should be a comma-delimited list of column names you want to sort by. Use
200          * a - prefix to sort a column in descending order (e.g., 'LastName,-Age' to sort first by LastName, then by Age descending).
201          * @param {Boolean} [config.saveInSession] Whether or not the definition of this query should be stored for reuse during the current session.
202          * If true, all information required to recreate the query will be stored on the server and a unique query name will be passed to the
203          * success callback.  This temporary query name can be used by all other API methods, including Query Web Part creation, for as long
204          * as the current user's session remains active.
205          * @param {Boolean} [config.includeDetailsColumn] Include the Details link column in the set of columns (defaults to false).
206          *       If included, the column will have the name "~~Details~~". The underlying table/query must support details links
207          *       or the column will be omitted in the response.
208          * @param {Object} [config.parameters] Map of name (string)/value pairs for the values of parameters if the SQL
209          *        references underlying queries that are parameterized. For example, the following passes two parameters to the query: {'Gender': 'M', 'CD4': '400'}.
210          *        The parameters are written to the request URL as follows: query.param.Gender=M&query.param.CD4=400.  For details on parameterized SQL queries, see
211          *        <a href="https://www.labkey.org/Documentation/wiki-page.view?name=paramsql">Parameterized SQL Queries</a>.
212          * @param {Double} [config.requiredVersion] If not set, or set to "8.3", the success handler will be passed a {@link LABKEY.Query.SelectRowsResults}
213          *       object. If set to "9.1" the success handler will be passed a {@link LABKEY.Query.ExtendedSelectRowsResults}
214          *       object. If greater than 13.2 the success handler will be passed a {@link LABKEY.Query.Response} object.
215          *       The main difference between SelectRowsResults and ExtendedSelectRowsResults is that each column in each row
216          *       will be another object (not just a scalar value) with a "value" property as well as other related properties
217          *       (url, mvValue, mvIndicator, etc.). In the LABKEY.Query.Response format each row will be an instance of
218          *       {@link LABKEY.Query.Row}.
219          *       In the "16.2" format, multi-value columns will be returned as an array of values, each of which may have a value, displayValue, and url.
220          *       In the "17.1" format, "formattedValue" may be included in the response as the display column's value formatted with the display column's format or folder format settings.
221          * @param {Integer} [config.timeout] The maximum number of milliseconds to allow for this operation before
222          *       generating a timeout error (defaults to 30000).
223          * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
224          * @returns {Mixed} In client-side scripts, this method will return a transaction id
225          * for the async request that can be used to cancel the request
226          * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
227          * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
228          * @example Example, from the Reagent Request Confirmation <a href="https://www.labkey.org/Documentation/wiki-page.view?name=reagentRequestConfirmation">Tutorial</a> and <a href="https://www.labkey.org/home/Study/demo/wiki-page.view?name=Confirmation">Demo</a>: <pre name="code" class="xml">
229          // This snippet extracts a table of UserID, TotalRequests and
230          // TotalQuantity from the "Reagent Requests" list.
231          // Upon success, the writeTotals function (not included here) uses the
232          // returned data object to display total requests and total quantities.
233 
234              LABKEY.Query.executeSql({
235                      containerPath: 'home/Study/demo/guestaccess',
236                      schemaName: 'lists',
237                      sql: 'SELECT "Reagent Requests".UserID AS UserID, \
238                          Count("Reagent Requests".UserID) AS TotalRequests, \
239                          Sum("Reagent Requests".Quantity) AS TotalQuantity \
240                          FROM "Reagent Requests" Group BY "Reagent Requests".UserID',
241                      success: writeTotals
242              });  </pre>
243 
244          * @see LABKEY.Query.SelectRowsOptions
245          * @see LABKEY.Query.SelectRowsResults
246          * @see LABKEY.Query.ExtendedSelectRowsResults
247          * @see LABKEY.Query.Response
248          */
249         executeSql : function(config)
250         {
251             var dataObject = {
252                 schemaName: config.schemaName,
253                 sql: config.sql
254             };
255 
256             // Work with Ext4.Ajax.request
257             if (config.saveInSession !== undefined && config.saveInSession !== null)
258                 dataObject.saveInSession = config.saveInSession;
259 
260             //set optional parameters
261             if (config.maxRows !== undefined && config.maxRows >= 0)
262                 dataObject.maxRows = config.maxRows;
263             if (config.offset && config.offset > 0)
264                 dataObject.offset = config.offset;
265             if (config.includeTotalCount != undefined)
266                 dataObject.includeTotalCount = config.includeTotalCount;
267 
268             if (config.containerFilter)
269                 dataObject.containerFilter = config.containerFilter;
270 
271             if (config.requiredVersion)
272                 dataObject.apiVersion = config.requiredVersion;
273 
274             if (config.includeStyle)
275                 dataObject.includeStyle = config.includeStyle;
276 
277             var qsParams = {};
278             if (config.sort)
279                 qsParams["query.sort"] = config.sort;
280 
281             if (config.parameters)
282             {
283                 for (var n in config.parameters)
284                 {
285                     if (config.parameters.hasOwnProperty(n))
286                     {
287                         qsParams["query.param." + n] = config.parameters[n];
288                     }
289                 }
290             }
291 
292             var requestConfig = {
293                 url : LABKEY.ActionURL.buildURL("query", "executeSql.api", config.containerPath, qsParams),
294                 method : 'POST',
295                 success: getSuccessCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.stripHiddenColumns, config.scope, config.requiredVersion),
296                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
297                 jsonData : dataObject,
298                 headers : {
299                     'Content-Type' : 'application/json'
300                 }
301             };
302 
303             if (LABKEY.Utils.isDefined(config.timeout))
304                 requestConfig.timeout = config.timeout;
305 
306             return LABKEY.Ajax.request(requestConfig);
307         },
308 
309         /**
310         * Select rows.
311         * @param {Object} config An object which contains the following configuration properties.
312         * @param {String} config.schemaName Name of a schema defined within the current container. See also: <a class="link"
313 					href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
314 					How To Find schemaName, queryName & viewName</a>.
315         * @param {String} config.queryName Name of a query table associated with the chosen schema. See also: <a class="link"
316 					href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
317 					How To Find schemaName, queryName & viewName</a>.
318         * @param {Function} config.success
319 				Function called when the "selectRows" function executes successfully.
320 				This function will be called with the following arguments:
321 				<ul>
322 				    <li>
323                         <b>data:</b> If config.requiredVersion is not set, or set to "8.3", the success handler will be
324                         passed a {@link LABKEY.Query.SelectRowsResults} object. If set to "9.1" the success handler will
325                         be passed a {@link LABKEY.Query.ExtendedSelectRowsResults} object. If greater than "13.2" the success
326                         handler will be passed a {@link LABKEY.Query.Response} object.
327                     </li>
328                     <li><b>responseObj:</b> The XMLHttpResponseObject instance used to make the AJAX request</li>
329 				    <li><b>options:</b> The options used for the AJAX request</li>
330 				</ul>
331         * @param {Function} [config.failure] Function called when execution of the "selectRows" function fails.
332         *       This function will be called with the following arguments:
333 				<ul>
334 				    <li><b>errorInfo:</b> an object describing the error with the following fields:
335                         <ul>
336                             <li><b>exception:</b> the exception message</li>
337                             <li><b>exceptionClass:</b> the Java class of the exception thrown on the server</li>
338                             <li><b>stackTrace:</b> the Java stack trace at the point when the exception occurred</li>
339                         </ul>
340                     </li>
341                     <li><b>responseObj:</b> the XMLHttpResponseObject instance used to make the AJAX request</li>
342 				    <li><b>options:</b> the options used for the AJAX request</li>
343 				</ul>
344         * @param {Array} [config.filterArray] Array of objects created by {@link LABKEY.Filter.create}.
345         * @param {Object} [config.parameters] Map of name (string)/value pairs for the values of parameters if the SQL
346         *        references underlying queries that are parameterized. For example, the following passes two parameters to the query: {'Gender': 'M', 'CD4': '400'}.
347         *        The parameters are written to the request URL as follows: query.param.Gender=M&query.param.CD4=400.  For details on parameterized SQL queries, see
348         *        <a href="https://www.labkey.org/Documentation/wiki-page.view?name=paramsql">Parameterized SQL Queries</a>.
349         * @param {String} [config.sort]  String description of the sort.  It includes the column names
350         *       listed in the URL of a sorted data region (with an optional minus prefix to indicate
351         *       descending order). In the case of a multi-column sort, up to three column names can be
352         *       included, separated by commas.
353         * @param {String} [config.viewName] The name of a custom view saved on the server for the specified query.
354         * @param {String} [config.columns] An Array of columns or a comma-delimited list of column names you wish to select from the specified
355         *       query. By default, selectRows will return the set of columns defined in the default value for this query,
356         *       as defined via the Customize View user interface on the server. You can override this by specifying a list
357         *       of column names in this parameter, separated by commas. The names can also include references to related
358         *       tables (e.g., 'RelatedPeptide/Peptide' where 'RelatedPeptide is the name of a foreign key column in the
359         *       base query, and 'Peptide' is the name of a column in the related table).
360         * @param {String} [config.containerPath] The path to the container in which the schema and query are defined,
361         *       if different than the current container. If not supplied, the current container's path will be used.
362          * @param {String} [config.containerFilter] One of the values of {@link LABKEY.Query.containerFilter} that sets
363          *       the scope of this query. Defaults to containerFilter.current, and is interpreted relative to
364          *       config.containerPath.
365         * @param {String} [config.showRows] Either 'paginated' (the default) 'selected', 'unselected', 'all', or 'none'.
366         *        When 'paginated', the maxRows and offset parameters can be used to page through the query's result set rows.
367         *        When 'selected' or 'unselected' the set of rows selected or unselected by the user in the grid view will be returned.
368         *        You can programatically get and set the selection using the {@link LABKEY.DataRegion.setSelected} APIs.
369         *        Setting <code>config.maxRows</code> to -1 is the same as 'all'
370         *        and setting <code>config.maxRows</code> to 0 is the same as 'none'.
371         * @param {Integer} [config.maxRows] The maximum number of rows to return from the server (defaults to 100000).
372         *        If you want to return all possible rows, set this config property to -1.
373         * @param {Integer} [config.offset] The index of the first row to return from the server (defaults to 0).
374         *        Use this along with the maxRows config property to request pages of data.
375         * @param {Boolean} [config.includeTotalCount] Include the total number of rows available (defaults to true).
376         *       If false totalCount will equal number of rows returned (equal to maxRows unless maxRows == 0).
377         * @param {Boolean} [config.includeDetailsColumn] Include the Details link column in the set of columns (defaults to false).
378         *       If included, the column will have the name "~~Details~~". The underlying table/query must support details links
379         *       or the column will be omitted in the response.
380         * @param {Boolean} [config.includeUpdateColumn] Include the Update (or edit) link column in the set of columns (defaults to false).
381         *       If included, the column will have the name "~~Update~~". The underlying table/query must support update links
382         *       or the column will be omitted in the response.
383         * @param {String} [config.selectionKey] Unique string used by selection APIs as a key when storing or retrieving the selected items for a grid.
384         *         Not used unless <code>config.showRows</code> is 'selected' or 'unselected'.
385         * @param {Boolean} [config.ignoreFilter] If true, the command will ignore any filter that may be part of the chosen view.
386         * @param {Integer} [config.timeout] The maximum number of milliseconds to allow for this operation before
387         *       generating a timeout error (defaults to 30000).
388         * @param {Double} [config.requiredVersion] If not set, or set to "8.3", the success handler will be passed a {@link LABKEY.Query.SelectRowsResults}
389         *        object. If set to "9.1" the success handler will be passed a {@link LABKEY.Query.ExtendedSelectRowsResults}
390         *        object. If greater than "13.2" the success handler will be passed a {@link LABKEY.Query.Response} object.
391         *        The main difference between SelectRowsResults and ExtendedSelectRowsResults is that each column in each row
392         *        will be another object (not just a scalar value) with a "value" property as well as other related properties
393         *        (url, mvValue, mvIndicator, etc.). In the LABKEY.Query.Response format each row will an instance of
394         *        {@link LABKEY.Query.Row}.
395          *       In the "16.2" format, multi-value columns will be returned as an array of values, each of which may have a value, displayValue, and url.
396          *       In the "17.1" format, "formattedValue" may be included in the response as the display column's value formatted with the display column's format or folder format settings.
397         * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
398          * @returns {Mixed} In client-side scripts, this method will return a transaction id
399          * for the async request that can be used to cancel the request
400          * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
401          * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
402         * @example Example: <pre name="code" class="xml">
403 <script type="text/javascript">
404 	function onFailure(errorInfo, options, responseObj)
405 	{
406 	    if (errorInfo && errorInfo.exception)
407 	        alert("Failure: " + errorInfo.exception);
408 	    else
409 	        alert("Failure: " + responseObj.statusText);
410 	}
411 
412 	function onSuccess(data)
413 	{
414 	    alert("Success! " + data.rowCount + " rows returned.");
415 	}
416 
417 	LABKEY.Query.selectRows({
418             schemaName: 'lists',
419             queryName: 'People',
420             columns: ['Name', 'Age'],
421             success: onSuccess,
422             failure: onFailure
423         });
424 </script> </pre>
425 		* @see LABKEY.Query.SelectRowsOptions
426 		* @see LABKEY.Query.SelectRowsResults
427         * @see LABKEY.Query.ExtendedSelectRowsResults
428         * @see LABKEY.Query.Response
429 		*/
430         selectRows : function(config)
431         {
432             //check for old-style separate arguments
433             if (arguments.length > 1)
434             {
435                 config = {
436                     schemaName: arguments[0],
437                     queryName: arguments[1],
438                     success: arguments[2],
439                     errorCallback: arguments[3],
440                     filterArray: arguments[4],
441                     sort: arguments[5],
442                     viewName: arguments[6]
443                 };
444             }
445 
446             if (!config.schemaName)
447                 throw "You must specify a schemaName!";
448             if (!config.queryName)
449                 throw "You must specify a queryName!";
450 
451             config.dataRegionName = config.dataRegionName || "query";
452 
453             var dataObject = LABKEY.Query.buildQueryParams(
454                     config.schemaName,
455                     config.queryName,
456                     config.filterArray,
457                     config.sort,
458                     config.dataRegionName
459             );
460 
461             if (!config.showRows || config.showRows == 'paginated')
462             {
463                 if (config.offset)
464                     dataObject[config.dataRegionName + '.offset'] = config.offset;
465 
466                 if (config.maxRows != undefined)
467                 {
468                     if (config.maxRows < 0)
469                         dataObject[config.dataRegionName + '.showRows'] = "all";
470                     else
471                         dataObject[config.dataRegionName + '.maxRows'] = config.maxRows;
472                 }
473             }
474             else if (config.showRows in {'all':true, 'selected':true, 'unselected':true, 'none':true})
475             {
476                 dataObject[config.dataRegionName + '.showRows'] = config.showRows;
477             }
478 
479 
480             if (config.viewName)
481                 dataObject[config.dataRegionName + '.viewName'] = config.viewName;
482 
483             if (config.columns)
484                 dataObject[config.dataRegionName + '.columns'] = LABKEY.Utils.isArray(config.columns) ? config.columns.join(",") : config.columns;
485 
486             if (config.selectionKey)
487                 dataObject[config.dataRegionName + '.selectionKey'] = config.selectionKey;
488 
489             if (config.ignoreFilter)
490                 dataObject[config.dataRegionName + '.ignoreFilter'] = 1;
491 
492             if (config.parameters)
493             {
494                 for (var propName in config.parameters)
495                 {
496                     if (config.parameters.hasOwnProperty(propName))
497                         dataObject[config.dataRegionName + '.param.' + propName] = config.parameters[propName];
498                 }
499             }
500 
501             if (config.requiredVersion)
502                 dataObject.apiVersion = config.requiredVersion;
503 
504             if (config.containerFilter)
505                 dataObject.containerFilter = config.containerFilter;
506 
507             if (config.includeTotalCount)
508                 dataObject.includeTotalCount = config.includeTotalCount;
509 
510             if (config.includeDetailsColumn)
511                 dataObject.includeDetailsColumn = config.includeDetailsColumn;
512 
513             if (config.includeUpdateColumn)
514                 dataObject.includeUpdateColumn = config.includeUpdateColumn;
515 
516             if (config.includeStyle)
517                 dataObject.includeStyle = config.includeStyle;
518 
519             var requestConfig = {
520                 url : LABKEY.ActionURL.buildURL('query', 'getQuery.api', config.containerPath),
521                 method : getMethod(config.method),
522                 success: getSuccessCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.stripHiddenColumns, config.scope, config.requiredVersion),
523                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
524                 params : dataObject
525             };
526 
527             if (LABKEY.Utils.isDefined(config.timeout))
528                 requestConfig.timeout = config.timeout;
529 
530             return LABKEY.Ajax.request(requestConfig);
531         },
532 
533         /**
534          * Select Distinct Rows
535          * @param {Object} config An object which contains the following configuration properties.
536          * @param {String} config.schemaName Name of a schema defined within the current container. See also: <a class="link"
537                         href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
538                         How To Find schemaName, queryName & viewName</a>.
539          * @param {String} config.queryName Name of a query table associated with the chosen schema.  See also: <a class="link"
540                         href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
541                         How To Find schemaName, queryName & viewName</a>.
542          * @param {String} config.column A single column for which the distinct results will be requested. This column
543          *              must exist within the specified query.
544          * @param {String} [config.containerFilter] One of the values of {@link LABKEY.Query.containerFilter} that sets
545          *       the scope of this query. Defaults to containerFilter.current, and is interpreted relative to
546          *       config.containerPath.
547          * @param {Object} [config.parameters] Map of name (string)/value pairs for the values of parameters if the SQL
548          *        references underlying queries that are parameterized. For example, the following passes two parameters to the query: {'Gender': 'M', 'CD4': '400'}.
549          *        The parameters are written to the request URL as follows: query.param.Gender=M&query.param.CD4=400.  For details on parameterized SQL queries, see
550          *        <a href="https://www.labkey.org/Documentation/wiki-page.view?name=paramsql">Parameterized SQL Queries</a>.
551          * @param {Array} [config.filterArray] Array of objects created by {@link LABKEY.Filter.create}.
552          * @param {String} [config.viewName] Name of a view to use.  This is potentially important if this view contains filters on the data.
553          * @param {Function} config.success
554          * @param {Function} config.failure
555          * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
556          */
557         selectDistinctRows : function(config)
558         {
559             if (!config.schemaName)
560                 throw "You must specify a schemaName!";
561             if (!config.queryName)
562                 throw "You must specify a queryName!";
563             if (!config.column)
564                 throw "You must specify a column!";
565 
566             config.dataRegionName = config.dataRegionName || "query";
567 
568             var dataObject = LABKEY.Query.buildQueryParams(
569                     config.schemaName,
570                     config.queryName,
571                     config.filterArray,
572                     config.sort,
573                     config.dataRegionName
574             );
575 
576             dataObject[config.dataRegionName + '.columns'] = config.column;
577 
578             if (config.viewName)
579                 dataObject[config.dataRegionName + '.viewName'] = config.viewName;
580 
581             if (config.maxRows && config.maxRows >= 0)
582                 dataObject.maxRows = config.maxRows;
583 
584             if (config.containerFilter)
585                 dataObject.containerFilter = config.containerFilter;
586 
587             if (config.parameters)
588             {
589                 for (var propName in config.parameters)
590                 {
591                     if (config.parameters.hasOwnProperty(propName))
592                         dataObject[config.dataRegionName + '.param.' + propName] = config.parameters[propName];
593                 }
594             }
595 
596             if (config.ignoreFilter)
597             {
598                 dataObject[config.dataRegionName + '.ignoreFilter'] = true;
599             }
600 
601             return LABKEY.Ajax.request({
602                 url : LABKEY.ActionURL.buildURL('query', 'selectDistinct.api', config.containerPath),
603                 method : getMethod(config.method),
604                 success: getSuccessCallbackWrapper(LABKEY.Utils.getOnSuccess(config), false, config.scope),
605                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
606                 params : dataObject
607             });
608         },
609 
610 
611         /**
612          * Returns a list of reports, views and/or datasets in a container
613          * @param config
614          * @param {String} [config.containerPath] A container path in which to execute this command.  If not provided, the current container will be used
615          * @param {Array} [config.dataTypes] An array of data types to return, which can be any of: 'reports', 'datasets' or 'queries'.  If null, all will be returned
616          * @param {Function} [config.success] A function called on success.  It will be passed a single argument with the following properties:
617          * <ul>
618          * <li>data: An array with one element per dataview.  Each view is a map with the following properties:
619          * <ul>
620          * <li>access:
621          * <li>allowCustomThumbnail: A flag indicating whether the thumbnail can be customized
622          * <li>category: The category to which this item has been assigned
623          * <li>categoryDisplayOrder: The display order within that category
624          * <li>container: The container where this dataView is defined
625          * <li>created: The displayName of the user who created the item
626          * <li>createdByUserId: The user Id of the user who created the item
627          * <li>dataType: The dataType of this item, either queries, reports or datasets
628          * <li>detailsUrl: The url that will display additional details about this item
629          * <li>icon: The url of the icon for this report
630          * <li>id: The unique Id of this item
631          * <li>reportId: The unique report Id if this item is a report. Value is null if this item is not a report.
632          * <li>modified: The date this item was last modified
633          * <li>name: The display name of this item
634          * <li>runUrl: The url that can be used to execute this report
635          * <li>shared: A flag indicating whether this item is shared
636          * <li>thumbnail: The url of this item's thumbnail image
637          * <li>type: The display string for the Data Type.
638          * <li>visible: A flag indicating whether this report is visible or hidden
639          * </ul>
640          * <li>types: a map of each dataType, and a boolean indicating whether it was included in the results (this is based on the dataTypes param in the config)
641          * </ul>
642          * @param {Function} [config.failure] A function called when execution of "getDataViews" fails.
643          * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
644          */
645         getDataViews : function(config)
646         {
647             var dataObject = {
648                 includeData: true,
649                 includeMetadata: false
650             };
651             if(config.dataTypes)
652                 dataObject.dataTypes = config.dataTypes;
653 
654             var callbackFn = LABKEY.Utils.getOnSuccess(config);
655             var success = LABKEY.Utils.getCallbackWrapper(function(data, response, options){
656                                             if (callbackFn)
657                                                 callbackFn.call(config.scope || this, data.data, options, response);
658                                         }, this);
659 
660             return LABKEY.Ajax.request({
661                 url : LABKEY.ActionURL.buildURL('reports', 'browseData.api', config.containerPath),
662                 method : 'POST',
663                 success: success,
664                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
665                 jsonData : dataObject,
666                 headers : {
667                     'Content-Type' : 'application/json'
668                 }
669             });
670         },
671 
672         /**
673         * Update rows.
674         * @param {Object} config An object which contains the following configuration properties.
675         * @param {String} config.schemaName Name of a schema defined within the current container. See also: <a class="link"
676 					href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
677 					How To Find schemaName, queryName & viewName</a>.
678         * @param {String} config.queryName Name of a query table associated with the chosen schema.  See also: <a class="link"
679 					href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
680 					How To Find schemaName, queryName & viewName</a>.
681         * @param {Array} config.rows Array of record objects in which each object has a property for each field.
682         *               The row array must include the primary key column values and values for
683         *               other columns you wish to update.
684         * @param {Object} [config.extraContext] <b>Experimental:</b> Optional extra context object passed into the transformation/validation script environment.
685         * @param {Function} config.success Function called when the "updateRows" function executes successfully.
686         	    Will be called with arguments:
687                 the parsed response data ({@link LABKEY.Query.ModifyRowsResults}), the XMLHttpRequest object and
688                 (optionally) the "options" object ({@link LABKEY.Query.ModifyRowsOptions}).
689         * @param {Function} [config.failure] Function called when execution of the "updateRows" function fails.
690         *                   See {@link LABKEY.Query.selectRows} for more information on the parameters passed to this function.
691         * @param {String} [config.containerPath] The container path in which the schema and query name are defined.
692         *              If not supplied, the current container path will be used.
693         * @param {Integer} [config.timeout] The maximum number of milliseconds to allow for this operation before
694         *       generating a timeout error (defaults to 30000).
695         * @param {boolean} [config.transacted] Whether all of the updates should be done in a single transaction, so they all succeed or all fail. Defaults to true
696         * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
697          * @returns {Mixed} In client-side scripts, this method will return a transaction id
698          * for the async request that can be used to cancel the request
699          * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
700          * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
701 		* @see LABKEY.Query.ModifyRowsResults
702 		* @see LABKEY.Query.ModifyRowsOptions
703         */
704         updateRows : function(config)
705         {
706             if (arguments.length > 1)
707                 config = configFromArgs(arguments);
708             config.action = "updateRows.api";
709             return sendJsonQueryRequest(config);
710         },
711 
712         /**
713         * Save inserts, updates, and/or deletes to potentially multiple tables with a single request.
714         * @param {Object} config An object which contains the following configuration properties.
715         * @param {Array} config.commands An array of all of the update/insert/delete operations to be performed.
716         * Each command has the following structure:
717         * @param {String} config.commands[].schemaName Name of a schema defined within the current container. See also: <a class="link"
718 					href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
719 					How To Find schemaName, queryName & viewName</a>.
720         * @param {String} config.commands[].queryName Name of a query table associated with the chosen schema.  See also: <a class="link"
721 					href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
722 					How To Find schemaName, queryName & viewName</a>.
723         * @param {String} config.commands[].command Name of the command to be performed. Must be one of "insert", "update", or "delete".
724         * @param {Array} config.commands[].rows An array of data for each row to be changed. See {@link LABKEY.Query.insertRows},
725         * {@link LABKEY.Query.updateRows}, or {@link LABKEY.Query.deleteRows} for requirements of what data must be included for each row.
726         * @param {Object} [config.commands[].extraContext] <b>Experimental:</b> Optional extra context object passed into the transformation/validation script environment.
727         * @param {Object} [config.extraContext] <b>Experimental:</b> Optional extra context object passed into the transformation/validation script environment.
728         * The extraContext at the command-level will be merged with the extraContext at the top-level of the config.
729         * @param {Function} config.success Function called when the "saveRows" function executes successfully.
730         	    Called with arguments:
731                 <ul>
732                     <li>an object with the following properties:
733                     <ul>
734                         <li><strong>result</strong>: an array of parsed response data ({@link LABKEY.Query.ModifyRowsResults}) (one for each command in the request)
735                         <li><strong>errorCount</strong>: an integer, with the total number of errors encountered during the operation
736                         <li><strong>committed</strong>: a boolean, indicating if the changes were actually committed to the database
737                     </ul>
738                     <li>the XMLHttpRequest object</li>
739                     <li>(optionally) the "options" object ({@link LABKEY.Query.ModifyRowsOptions})</li>
740                 </ul>
741         * @param {Function} [config.failure] Function called if execution of the "saveRows" function fails.
742         *                   See {@link LABKEY.Query.selectRows} for more information on the parameters passed to this function.
743         * @param {String} [config.containerPath] The container path in which the changes are to be performed.
744         *              If not supplied, the current container path will be used.
745         * @param {Integer} [config.timeout] The maximum number of milliseconds to allow for this operation before
746         *       generating a timeout error (defaults to 30000).
747         * @param {Double} [config.apiVersion] Version of the API. If this is 13.2 or higher, a request that fails
748         * validation will be returned as a successful response. Use the 'errorCount' and 'committed' properties in the
749         * response to tell if it committed or not. If this is 13.1 or lower (or unspecified), the failure callback
750         * will be invoked instead in the event of a validation failure.
751         * @param {boolean} [config.transacted] Whether all of the row changes for all of the tables
752         * should be done in a single transaction, so they all succeed or all fail. Defaults to true
753         * @param {boolean} [config.validateOnly] Whether or not the server should attempt proceed through all of the
754         * commands, but not actually commit them to the database. Useful for scenarios like giving incremental
755         * validation feedback as a user fills out a UI form, but not actually save anything until they explicitly request
756         * a save.
757         * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
758          * @returns {Mixed} In client-side scripts, this method will return a transaction id
759          * for the async request that can be used to cancel the request
760          * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
761          * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
762 		* @see LABKEY.Query.ModifyRowsResults
763 		* @see LABKEY.Query.ModifyRowsOptions
764         */
765         saveRows : function(config)
766         {
767             if (arguments.length > 1)
768                 config = configFromArgs(arguments);
769 
770             var dataObject = {
771                 commands: config.commands,
772                 containerPath: config.containerPath,
773                 validateOnly : config.validateOnly,
774                 transacted : config.transacted,
775                 extraContext : config.extraContext,
776                 apiVersion : config.apiVersion
777             };
778 
779             var requestConfig = {
780                 url : LABKEY.ActionURL.buildURL("query", "saveRows.api", config.containerPath),
781                 method : 'POST',
782                 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope),
783                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
784                 jsonData : dataObject,
785                 headers : {
786                     'Content-Type' : 'application/json'
787                 }
788             };
789 
790             if (LABKEY.Utils.isDefined(config.timeout))
791                 requestConfig.timeout = config.timeout;
792 
793             return LABKEY.Ajax.request(requestConfig);
794 
795         },
796 
797         /**
798         * Insert rows.
799         * @param {Object} config An object which contains the following configuration properties.
800         * @param {String} config.schemaName Name of a schema defined within the current container.  See also: <a class="link"
801 					href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
802 					How To Find schemaName, queryName & viewName</a>.
803         * @param {String} config.queryName Name of a query table associated with the chosen schema. See also: <a class="link"
804 					href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
805 					How To Find schemaName, queryName & viewName</a>.
806         * @param {Array} config.rows Array of record objects in which each object has a property for each field.
807         *                  The row data array must include all column values except for the primary key column.
808         *                  However, you will need to include the primary key column values if you defined
809         *                  them yourself instead of relying on auto-number.
810         * @param {Object} [config.extraContext] <b>Experimental:</b> Optional extra context object passed into the transformation/validation script environment.
811         * @param {Function} config.success Function called when the "insertRows" function executes successfully.
812 						Will be called with the following arguments:
813                         the parsed response data ({@link LABKEY.Query.ModifyRowsResults}), the XMLHttpRequest object and
814                         (optionally) the "options" object ({@link LABKEY.Query.ModifyRowsOptions}).
815 		* @param {Function} [config.failure]  Function called when execution of the "insertRows" function fails.
816         *                   See {@link LABKEY.Query.selectRows} for more information on the parameters passed to this function.
817         * @param {String} [config.containerPath] The container path in which the schema and query name are defined.
818         *              If not supplied, the current container path will be used.
819         * @param {Integer} [config.timeout] The maximum number of milliseconds to allow for this operation before
820         *       generating a timeout error (defaults to 30000).
821         * @param {boolean} [config.transacted] Whether all of the inserts should be done in a single transaction, so they all succeed or all fail. Defaults to true
822         * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
823          * @returns {Mixed} In client-side scripts, this method will return a transaction id
824          * for the async request that can be used to cancel the request
825          * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
826          * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
827         * @example Example, from the Reagent Request <a href="https://www.labkey.org/Documentation/wiki-page.view?name=reagentRequestForm">Tutorial</a> and <a href="https://www.labkey.org/home/Study/demo/wiki-page.view?name=reagentRequest">Demo</a>: <pre name="code" class="xml">
828          // This snippet inserts data from the ReagentReqForm into a list.
829          // Upon success, it moves the user to the confirmation page and
830          // passes the current user's ID to that page.
831          LABKEY.Query.insertRows({
832              containerPath: '/home/Study/demo/guestaccess',
833              schemaName: 'lists',
834              queryName: 'Reagent Requests',
835              rows: [{
836                 "Name":  ReagentReqForm.DisplayName.value,
837                 "Email": ReagentReqForm.Email.value,
838                 "UserID": ReagentReqForm.UserID.value,
839                 "Reagent": ReagentReqForm.Reagent.value,
840                 "Quantity": parseInt(ReagentReqForm.Quantity.value),
841                 "Date": new Date(),
842                 "Comments": ReagentReqForm.Comments.value,
843                 "Fulfilled": 'false'
844              }],
845              successCallback: function(data){
846                  window.location =
847                     '/home/Study/demo/wiki-page.view?name=confirmation&userid='
848                     + LABKEY.Security.currentUser.id;
849              },
850          });  </pre>
851 		* @see LABKEY.Query.ModifyRowsResults
852 		* @see LABKEY.Query.ModifyRowsOptions
853         */
854         insertRows : function(config)
855         {
856             if (arguments.length > 1)
857                 config = configFromArgs(arguments);
858             config.action = "insertRows.api";
859             return sendJsonQueryRequest(config);
860         },
861 
862         /**
863         * Delete rows.
864         * @param {Object} config An object which contains the following configuration properties.
865         * @param {String} config.schemaName Name of a schema defined within the current container. See also: <a class="link"
866 					href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
867 					How To Find schemaName, queryName & viewName</a>.
868         * @param {String} config.queryName Name of a query table associated with the chosen schema. See also: <a class="link"
869 					href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
870 					How To Find schemaName, queryName & viewName</a>.
871         * @param {Object} [config.extraContext] <b>Experimental:</b> Optional extra context object passed into the transformation/validation script environment.
872         * @param {Function} config.success Function called when the "deleteRows" function executes successfully.
873                      Will be called with the following arguments:
874                      the parsed response data ({@link LABKEY.Query.ModifyRowsResults}), the XMLHttpRequest object and
875                      (optionally) the "options" object ({@link LABKEY.Query.ModifyRowsOptions}).
876 		* @param {Function} [config.failure] Function called when execution of the "deleteRows" function fails.
877          *                   See {@link LABKEY.Query.selectRows} for more information on the parameters passed to this function.
878         * @param {Array} config.rows Array of record objects in which each object has a property for each field.
879         *                  The row data array needs to include only the primary key column value, not all columns.
880         * @param {String} [config.containerPath] The container path in which the schema and query name are defined.
881         *              If not supplied, the current container path will be used.
882         * @param {Integer} [config.timeout] The maximum number of milliseconds to allow for this operation before
883         *       generating a timeout error (defaults to 30000).
884         * @param {boolean} [config.transacted] Whether all of the deletes should be done in a single transaction, so they all succeed or all fail. Defaults to true
885         * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
886          * @returns {Mixed} In client-side scripts, this method will return a transaction id
887          * for the async request that can be used to cancel the request
888          * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
889          * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
890 		* @see LABKEY.Query.ModifyRowsResults
891 		* @see LABKEY.Query.ModifyRowsOptions
892         */
893         deleteRows : function(config)
894         {
895             if (arguments.length > 1)
896             {
897                 config = configFromArgs(arguments);
898             }
899             config.action = "deleteRows.api";
900             return sendJsonQueryRequest(config);
901         },
902 
903         /**
904          * Delete a query view.
905          * @param config An object that contains the following configuration parameters
906          * @param {String} config.schemaName The name of the schema.
907          * @param {String} config.queryName the name of the query.
908          * @param {String} [config.viewName] the name of the view. If a viewName is not specified, the default view will be deleted/reverted.
909          * @param {boolean} [config.revert] Optionally, the view can be reverted instead of deleted. Defaults to false.
910          */
911         deleteQueryView : function(config) {
912             if (!config) {
913                 throw 'You must specify a configuration!'
914             }
915             if (!config.schemaName) {
916                 throw 'You must specify a schemaName!'
917             }
918             if (!config.queryName) {
919                 throw 'You must specify a queryName!'
920             }
921 
922             var params = {
923                 schemaName: config.schemaName,
924                 queryName: config.queryName
925             };
926 
927             if (config.viewName) {
928                 params.viewName = config.viewName;
929             }
930 
931             if (config.revert !== undefined) {
932                 params.complete = config.revert !== true;
933             }
934 
935             return LABKEY.Ajax.request({
936                 url: LABKEY.ActionURL.buildURL('query', 'deleteView.api', config.containerPath),
937                 method: 'POST',
938                 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope),
939                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
940                 jsonData: params
941             });
942         },
943 
944         /**
945          * Build and return an object suitable for passing to the
946          * <a href = "http://www.extjs.com/deploy/dev/docs/?class=Ext.Ajax">Ext.Ajax</a> 'params' configuration property.
947          * @param {string} schemaName Name of a schema defined within the current container.  See also: <a class="link"
948          href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
949          How To Find schemaName, queryName & viewName</a>.
950          * @param {string} queryName Name of a query table associated with the chosen schema.   See also: <a class="link"
951          href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
952          How To Find schemaName, queryName & viewName</a>.
953          * @param {LABKEY.Filter[]} [filterArray] Array of objects created by {@link LABKEY.Filter.create}.
954          * @param {string} [sort]  String description of the sort.  It includes the column names
955          *       listed in the URL of a sorted data region (with an optional minus prefix to indicate
956          *       descending order). In the case of a multi-column sort, up to three column names can be
957          *       included, separated by commas.
958          * @param {string} [dataRegionName=query]
959          * @returns {Object} Object suitable for passing to the
960          * <a href = "http://extjs.com/deploy/ext-2.2.1/docs/?class=Ext.Ajax">Ext.Ajax</a> 'params' configuration property.
961          */
962         buildQueryParams: function(schemaName, queryName, filterArray, sort, dataRegionName)
963         {
964             dataRegionName = dataRegionName || "query";
965             var params = {};
966             params.dataRegionName = dataRegionName;
967             params[dataRegionName + '.queryName'] = queryName;
968             params.schemaName = schemaName;
969             if (sort)
970             {
971                 params[dataRegionName + '.sort'] = sort;
972             }
973 
974             LABKEY.Filter.appendFilterParams(params, filterArray, dataRegionName);
975 
976             return params;
977         },
978 
979         /**
980          * Returns the set of schemas available in the specified container.
981          * @param config An object that contains the following configuration parameters
982          * @param {String} config.schemaName Get schemas under the given schemaName.
983          * @param {String} config.apiVersion Version of the API. Changed the structure of the server's response.
984          * @param {String} config.includeHidden Default true.
985          * @param {function} config.success The function to call when the function finishes successfully.
986          * This function will be called with the following parameters:
987          * <ul>
988          * <li><b>schemasInfo:</b> An object with a property called "schemas". If no apiVersion is specified, or it is
989          * less than 9.3, it will be an array of schema names. If apiVersion is 9.3 or greater, it will be a map where
990          * the keys are schemaNames and the values are objects with the following properties:
991          *     <ul>
992          *         <li><b>schemaName</b>: the short name of the schema</li>
993          *         <li><b>fullyQualifiedName</b>: the fully qualified name of the schema, encoded as a string with
994          *         "." separators as described in {@link LABKEY.SchemaKey}</li>
995          *         <li><b>description</b>: a short description of the schema</li>
996          *         <li><b>schemas</b>: a map of child schemas, with values in the same structure as this object</li>
997          *     </ul>
998          * </li>
999          * </ul>
1000          * @param {function} [config.failure] The function to call if this function encounters an error.
1001          * This function will be called with the following parameters:
1002          * <ul>
1003          * <li><b>errorInfo:</b> An object with a property called "exception," which contains the error message.</li>
1004          * </ul>
1005          * @param {String} [config.containerPath] A container path in which to execute this command. If not supplied,
1006          * the current container will be used.
1007          * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
1008          * @returns {Mixed} In client-side scripts, this method will return a transaction id
1009          * for the async request that can be used to cancel the request
1010          * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
1011          * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
1012          */
1013         getSchemas : function(config)
1014         {
1015             var params = {};
1016             if (config.apiVersion)
1017                 params.apiVersion = config.apiVersion;
1018             if (config.schemaName)
1019                 params.schemaName = config.schemaName;
1020 
1021             if (config.hasOwnProperty("includeHidden"))
1022                 params.includeHidden = config.includeHidden;
1023 
1024             return LABKEY.Ajax.request({
1025                 url : LABKEY.ActionURL.buildURL('query', 'getSchemas.api', config.containerPath),
1026                 method : 'GET',
1027                 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope),
1028                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
1029                 params: params
1030             });
1031         },
1032 
1033         /**
1034          * Returns the set of queries available in a given schema.
1035          * @param config An object that contains the following configuration parameters
1036          * @param {String} config.schemaName The name of the schema.
1037          * @param {function} config.success The function to call when the function finishes successfully.
1038          * This function will be called with the following parameters:
1039          * <ul>
1040          * <li><b>queriesInfo:</b> An object with the following properties
1041          *  <ul>
1042          *      <li><b>schemaName:</b> the name of the requested schema</li>
1043          *      <li><b>queries:</b> an array of objects, each of which has the following properties
1044          *          <ul>
1045          *              <li><b>name:</b> the name of the query</li>
1046          *              <li><b>title:</b> this is the label used when displaying this table. If the table has no title, this will be the same as the name.</li>
1047          *              <li><b>hidden:</b> true if this is a hidden query or table.
1048          *              <li><b>inherit:</b> true if this query is marked as inheritable in sub-folders.
1049          *              <li><b>isUserDefined:</b> true if this is a user-defined query</li>
1050          *              <li><b>canEdit:</b> true if the current user can edit this query</li>
1051          *              <li><b>isMetadataOverrideable:</b> true if the current user may override the query's metadata</li>
1052          *              <li><b>moduleName:</b> the module that defines this query</li>
1053          *              <li><b>isInherited:</b> true if this query is defined in a different container.</li>
1054          *              <li><b>containerPath:</b> if <code>isInherited</code>, the container path where this query is defined.</li>
1055          *              <li><b>description:</b> A description for this query (if provided)</li>
1056          *              <li><b>viewDataUrl:</b> the server-relative URL where this query's data can be viewed.
1057          *                  Available in LabKey Server version 10.2 and later.</li>
1058          *              <li><b>columns:</b> if config.includeColumns is not false, this will contain an array of
1059          *                 objects with the following properties
1060          *                  <ul>
1061          *                      <li><b>name:</b> the name of the column</li>
1062          *                      <li><b>caption:</b> the caption of the column (may be undefined)</li>
1063          *                      <li><b>description:</b> the description of the column (may be undefined)</li>
1064          *                  </ul>
1065          *              </li>
1066          *          </ul>
1067          *      </li>
1068          *  </ul>
1069          * </li>
1070          * </ul>
1071          * @param {function} [config.failure] The function to call if this function encounters an error.
1072          * This function will be called with the following parameters:
1073          * <ul>
1074          * <li><b>errorInfo:</b> An object with a property called "exception," which contains the error message.</li>
1075          * </ul>
1076          * @param {Boolean} [config.includeUserQueries] If set to false, user-defined queries will not be included in
1077          * the results. Default is true.
1078          * @param {Boolean} [config.includeSystemQueries] If set to false, system-defined queries will not be included in
1079          * the results. Default is true.
1080          * @param {Boolean} [config.includeColumns] If set to false, information about the available columns in this
1081          * query will not be included in the results. Default is true.
1082          * @param {String} [config.containerPath] A container path in which to execute this command. If not supplied,
1083          * the current container will be used.
1084          * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
1085          * @returns {Mixed} In client-side scripts, this method will return a transaction id
1086          * for the async request that can be used to cancel the request
1087          * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
1088          * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
1089          */
1090         getQueries : function(config)
1091         {
1092             var params = {};
1093             // Only pass the parameters that the server supports, and exclude ones like successCallback
1094             LABKEY.Utils.applyTranslated(params, config,
1095             {
1096                 schemaName: 'schemaName',
1097                 includeColumns: 'includeColumns',
1098                 includeUserQueries: 'includeUserQueries',
1099                 includeSystemQueries: 'includeSystemQueries'
1100             }, false, false);
1101 
1102             return LABKEY.Ajax.request({
1103                 url: LABKEY.ActionURL.buildURL('query', 'getQueries.api', config.containerPath),
1104                 method : 'GET',
1105                 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope),
1106                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
1107                 params: params
1108             });
1109         },
1110 
1111         /**
1112          * Returns the set of views available for a given query in a given schema.
1113          * @param config An object that contains the following configuration parameters
1114          * @param {String} config.schemaName The name of the schema.
1115          * @param {String} config.queryName the name of the query.
1116          * @param {String} [config.viewName] A view name (empty string for the default view), otherwise return all views for the query.
1117          * @param {Boolean} [config.metadata] Include view column field metadata.
1118          * @param {function} config.success The function to call when the function finishes successfully.
1119          * This function will be called with the following parameters:
1120          * <ul>
1121          * <li><b>viewsInfo:</b> An object with the following properties
1122          *  <ul>
1123          *      <li><b>schemaName:</b> the name of the requested schema</li>
1124          *      <li><b>queryName:</b> the name of the requested query</li>
1125          *      <li><b>views:</b> an array of objects, each of which has the following properties
1126          *          <ul>
1127          *              <li><b>name:</b> the name of the view (default view's name is empty string)</li>
1128          *              <li><b>label:</b> the label of the view</li>
1129          *              <li><b>default:</b> true if this is the default view info</li>
1130          *              <li><b>viewDataUrl:</b> the server-relative URL where this view's data can be viewed.
1131          *                  Available in LabKey Server version 10.2 and later.</li>
1132          *              <li><b>columns:</b> this will contain an array of objects with the following properties
1133          *                  <ul>
1134          *                      <li><b>name:</b> the name of the column</li>
1135          *                      <li><b>fieldKey:</b> the field key for the column (may include join column names, e.g. 'State/Population')</li>
1136          *                  </ul>
1137          *              </li>
1138          *              <li><b>filter:</b> TBD
1139          *                  Available in LabKey Server version 10.3 and later.</li>
1140          *              <li><b>sort:</b> TBD
1141          *                  Available in LabKey Server version 10.3 and later.</li>
1142          *              <li><b>fields:</b> TBD if metadata
1143          *                  Available in LabKey Server version 10.3 and later.</li>
1144          *          </ul>
1145          *      </li>
1146          *  </ul>
1147          * </li>
1148          * </ul>
1149          * @param {function} [config.failure] The function to call if this function encounters an error.
1150          * This function will be called with the following parameters:
1151          * <ul>
1152          * <li><b>errorInfo:</b> An object with a property called "exception," which contains the error message.</li>
1153          * </ul>
1154          * @param {String} [config.containerPath] A container path in which to execute this command. If not supplied,
1155          * the current container will be used.
1156          * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
1157          * @returns {Mixed} In client-side scripts, this method will return a transaction id
1158          * for the async request that can be used to cancel the request
1159          * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
1160          * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
1161          */
1162         getQueryViews : function(config)
1163         {
1164             var params = {};
1165             if (config.schemaName)
1166                 params.schemaName = config.schemaName;
1167             if (config.queryName)
1168                 params.queryName = config.queryName;
1169             if (config.viewName != undefined)
1170                 params.viewName = config.viewName;
1171             if (config.metadata)
1172                 params.metadata = config.metadata;
1173 
1174             return LABKEY.Ajax.request({
1175                 url: LABKEY.ActionURL.buildURL('query', 'getQueryViews.api', config.containerPath),
1176                 method : 'GET',
1177                 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope),
1178                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
1179                 params: params
1180             });
1181         },
1182 
1183         /**
1184          * Creates or updates a custom view or views for a given query in a given schema.  The config
1185          * object matches the viewInfos parameter of the getQueryViews.successCallback.
1186          * @param config An object that contains the following configuration parameters
1187          * @param {String} config.schemaName The name of the schema.
1188          * @param {String} config.queryName The name of the query.
1189          * @param {String} config.views The updated view definitions.
1190          * @param {function} config.success The function to call when the function finishes successfully.
1191          * This function will be called with the same parameters as getQueryViews.successCallback.
1192          * @param {function} [config.failure] The function to call if this function encounters an error.
1193          * This function will be called with the following parameters:
1194          * <ul>
1195          * <li><b>errorInfo:</b> An object with a property called "exception," which contains the error message.</li>
1196          * </ul>
1197          * @param {String} [config.containerPath] A container path in which to execute this command. If not supplied,
1198          * the current container will be used.
1199          * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
1200          * @returns {Mixed} In client-side scripts, this method will return a transaction id
1201          * for the async request that can be used to cancel the request
1202          * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
1203          * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
1204          */
1205         saveQueryViews : function (config)
1206         {
1207             var params = {};
1208             if (config.schemaName)
1209                 params.schemaName = config.schemaName;
1210             if (config.queryName)
1211                 params.queryName = config.queryName;
1212             if (config.views)
1213                 params.views = config.views;
1214 
1215             return LABKEY.Ajax.request({
1216                 url: LABKEY.ActionURL.buildURL('query', 'saveQueryViews.api', config.containerPath),
1217                 method: 'POST',
1218                 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope),
1219                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
1220                 jsonData : params,
1221                 headers : {
1222                     'Content-Type' : 'application/json'
1223                 }
1224             });
1225         },
1226 
1227         /**
1228          * Returns details about a given query including detailed information about result columns
1229          * @param {Object} config An object that contains the following configuration parameters
1230          * @param {String} config.schemaName The name of the schema.
1231          * @param {String} config.queryName The name of the query.
1232          * @param {String} [config.viewName] A view name or Array of view names to include custom view details. Use '*' to include all views for the query.
1233          * @param {String} [config.fields] A field key or Array of field keys to include in the metadata.
1234          * @param {Boolean} [config.initializeMissingView] Initialize the view based on the default view iff the view doesn't yet exist.
1235          * @param {function} config.success The function to call when the function finishes successfully.
1236          * This function will be called with the following parameters:
1237          * <ul>
1238          * <li><b>queryInfo:</b> An object with the following properties
1239          *  <ul>
1240          *      <li><b>schemaName:</b> the name of the requested schema</li>
1241          *      <li><b>name:</b> the name of the requested query</li>
1242          *      <li><b>isUserDefined:</b> true if this is a user-defined query</li>
1243          *      <li><b>canEdit:</b> true if the current user can edit this query</li>
1244          *      <li><b>isMetadataOverrideable:</b> true if the current user may override the query's metadata</li>
1245          *      <li><b>moduleName:</b> the module that defines this query</li>
1246          *      <li><b>isInherited:</b> true if this query is defined in a different container.</li>
1247          *      <li><b>containerPath:</b> if <code>isInherited</code>, the container path where this query is defined.</li>
1248          *      <li><b>viewDataUrl:</b> The URL to navigate to for viewing the data returned from this query</li>
1249          *      <li><b>title:</b> If a value has been set, this is the label used when displaying this table</li>
1250          *      <li><b>description:</b> A description for this query (if provided)</li>
1251          *      <li><b>columns:</b> Information about all columns in this query. This is an array of LABKEY.Query.FieldMetaData objects.</li>
1252          *      <li><b>defaultView:</b> An array of column information for the columns in the current user's default view of this query.
1253          *      The shape of each column info is the same as in the columns array.</li>
1254          *      <li><b>views:</b> An array of view info (XXX: same as views.getQueryViews()
1255          *  </ul>
1256          * </li>
1257          * </ul>
1258          * @see LABKEY.Query.FieldMetaData
1259          * @param {function} [config.failure] The function to call if this function encounters an error.
1260          * This function will be called with the following parameters:
1261          * <ul>
1262          * <li><b>errorInfo:</b> An object with a property called "exception," which contains the error message.</li>
1263          * </ul>
1264          * @param {String} [config.containerPath] A container path in which to execute this command. If not supplied,
1265          * the current container will be used.
1266          * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
1267          * @returns {Mixed} In client-side scripts, this method will return a transaction id
1268          * for the async request that can be used to cancel the request
1269          * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
1270          * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
1271          */
1272         getQueryDetails : function(config)
1273         {
1274             var params = {};
1275             if (config.schemaName)
1276                 params.schemaName = config.schemaName;
1277 
1278             if (config.queryName)
1279                 params.queryName = config.queryName;
1280 
1281             if (config.viewName != undefined)
1282                 params.viewName = config.viewName;
1283 
1284             if (config.fields)
1285                 params.fields = config.fields;
1286 
1287             if (config.fk)
1288                 params.fk = config.fk;
1289 
1290             if (config.initializeMissingView)
1291                 params.initializeMissingView = config.initializeMissingView;
1292 
1293             return LABKEY.Ajax.request({
1294                 url: LABKEY.ActionURL.buildURL('query', 'getQueryDetails.api', config.containerPath),
1295                 method : 'GET',
1296                 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope),
1297                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
1298                 params: params
1299             });
1300         },
1301 
1302         /**
1303          * Validates the specified query by ensuring that it parses and executes without an exception.
1304          * @param config An object that contains the following configuration parameters
1305          * @param {String} config.schemaName The name of the schema.
1306          * @param {String} config.queryName the name of the query.
1307          * @param {Boolean} config.includeAllColumns If set to false, only the columns in the user's default view
1308          * of the specific query will be tested (defaults to true).
1309          * @param {Boolean} config.validateQueryMetadata If true, the query metadata and custom views will also be validated.
1310          * @param {function} config.success The function to call when the function finishes successfully.
1311          * This function will be called with a simple object with one property named "valid" set to true.
1312          * @param {function} [config.failure] The function to call if this function encounters an error.
1313          * This function will be called with the following parameters:
1314          * <ul>
1315          * <li><b>errorInfo:</b> An object with a property called "exception," which contains the error message. If validateQueryMetadata was used, this will also hae a property called 'errors', which is an array of objects describing each error.</li>
1316          * </ul>
1317          * @param {String} [config.containerPath] A container path in which to execute this command. If not supplied,
1318          * the current container will be used.
1319          * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
1320          * @returns {Mixed} In client-side scripts, this method will return a transaction id
1321          * for the async request that can be used to cancel the request
1322          * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
1323          * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
1324          */
1325         validateQuery : function(config)
1326         {
1327             var params = {};
1328 
1329             LABKEY.Utils.applyTranslated(params, config, {
1330                 successCallback: false,
1331                 errorCallback: false,
1332                 scope: false
1333             });
1334 
1335             return LABKEY.Ajax.request({
1336                 url: LABKEY.ActionURL.buildURL('query', (config.validateQueryMetadata ? 'validateQueryMetadata.api' : 'validateQuery.api'), config.containerPath),
1337                 method : 'GET',
1338                 success: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnSuccess(config), config.scope),
1339                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope, true),
1340                 params: params
1341             });
1342         },
1343 
1344         /**
1345          * Returns the current date/time on the LabKey server.
1346          * @param config An object that contains the following configuration parameters
1347          * @param {function} config.success The function to call when the function finishes successfully.
1348          * This function will be called with a single parameter of type Date.
1349          * @param {function} [config.failure] The function to call if this function encounters an error.
1350          * This function will be called with the following parameters:
1351          * <ul>
1352          * <li><b>errorInfo:</b> An object with a property called "exception," which contains the error message.</li>
1353          * </ul>
1354          * @returns {Mixed} In client-side scripts, this method will return a transaction id
1355          * for the async request that can be used to cancel the request
1356          * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
1357          * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
1358          */
1359         getServerDate : function(config)
1360         {
1361             return LABKEY.Ajax.request({
1362                 url: LABKEY.ActionURL.buildURL('query', 'getServerDate.api'),
1363                 failure: LABKEY.Utils.getCallbackWrapper(LABKEY.Utils.getOnFailure(config), config.scope),
1364                 success: LABKEY.Utils.getCallbackWrapper(function(json){
1365                     var d;
1366                     var onSuccess = LABKEY.Utils.getOnSuccess(config);
1367                     if (json && json.date && onSuccess)
1368                     {
1369                         d = new Date(json.date);
1370                         onSuccess(d);
1371                     }
1372                 }, this)
1373             });
1374         },
1375 
1376 
1377         /**
1378          * Converts a javascript date into a format suitable for using in a LabKey SQL query, includes time but not milliseconds.
1379          * @param {Date} date JavaScript date
1380          * @param {Boolean} withMS include milliseconds
1381          * @returns {String} a date and time literal formatted to be used in a LabKey query
1382          */
1383         sqlDateTimeLiteral : function(date, withMS)
1384         {
1385             if (date === undefined || date === null || !date)
1386                 return "NULL";
1387             if (typeof date == "string")
1388             {
1389                 try { date = new Date(date); } catch (x) { }
1390             }
1391             if (typeof date == "object" && typeof date.toISOString == "function")
1392             {
1393                 var fmt2 = function(a) {return (a>=10 ?  ""+a : "0"+a);};
1394                 var fmt3 = function(a) {return (a>=100 ? ""+a : "0"+fmt2(a));};
1395                 return "{ts '" +
1396                         date.getFullYear() + "-" + fmt2(date.getMonth()+1) + "-" +fmt2(date.getDate()) + " " + fmt2(date.getHours()) + ":" + fmt2(date.getMinutes()) + ":" + fmt2(date.getSeconds()) +
1397                         (withMS ? "." + fmt3(date.getMilliseconds()) : "")
1398                         + "'}";
1399             }
1400             return "{ts '" + this.sqlStringLiteral(date) + "'}";
1401         },
1402 
1403 
1404         /**
1405          * Converts a JavaScript date into a format suitable for using in a LabKey SQL query, does not include time.
1406          * @param {Date} date JavaScript date
1407          * @returns {String} a date literal formatted to be used in a LabKey query
1408          */
1409         sqlDateLiteral : function(date)
1410         {
1411             if (date === undefined || date === null || !date)
1412                 return "NULL";
1413             if (typeof date == "string")
1414             {
1415                 try { date = new Date(date); } catch (x) { }
1416             }
1417             if (typeof date == "object" && typeof date.toISOString == "function")
1418             {
1419                 var fmt2 = function(a) {return (a>=10 ? a : "0"+a);};
1420                 var fmt3 = function(a) {return (a>=999 ? a : "0"+fmt2(a));};
1421                 return "{d '" +
1422                         date.getFullYear() + "-" + fmt2(date.getMonth()+1) + "-" +fmt2(date.getDate())
1423                         + "'}";
1424             }
1425             return "{d '" + this.sqlStringLiteral(date) + "'}";
1426         },
1427 
1428 
1429         /**
1430          * Converts a JavaScript string into a format suitable for using in a LabKey SQL query.
1431          * @param {string} str String to use in query
1432          * @returns {string} value formatted for use in a LabKey query.  Will properly escape single quote characters.
1433          */
1434         sqlStringLiteral : function(str)
1435         {
1436             if (str === undefined || str === null || str == '')
1437                 return "NULL";
1438             str = str.toString();
1439             return "'" + str.replace("'","''") + "'";
1440         },
1441 
1442         URL_COLUMN_PREFIX: "_labkeyurl_"
1443     };
1444 };
1445 
1446 /**
1447  * @class This class is used to construct filters when using APIs such as {@link LABKEY.Query.GetData.getRawData},
1448  *      {@link LABKEY.Query.selectRows}, or {@link LABKEY.Query.executeSql}. This is the base filter class, which requires
1449  *      the user specify a filter type from {@link LABKEY.Filter#Types}. Users can avoid the need for specifying a filter
1450  *      type by using a subclass of Filter such as {@link LABKEY.Query.Filter.Equals} or {@link LABKEY.Query.Filter.GreaterThan}, which
1451  *      will automatically set the type for the user.
1452  * @param {String} columnName Required. The name of the column the filter will be applied  Can be a string, array of strings,
1453  * or a {@link LABKEY.FieldKey}
1454  * @param value Value used as the filter criterion or an Array of values.
1455  * @param {LABKEY.Filter#Types} filterType Type of filter to apply to the 'column' using the 'value'
1456  * @constructor
1457  */
1458 LABKEY.Query.Filter = function (columnName, value, filterType)
1459 {
1460     if (columnName) {
1461         if (columnName instanceof LABKEY.FieldKey) {
1462             columnName = columnName.toString();
1463         }
1464         else if (columnName instanceof Array) {
1465             columnName = columnName.join('/');
1466         }
1467     }
1468 
1469     if (!filterType)
1470     {
1471         filterType = LABKEY.Filter.Types.EQUAL;
1472     }
1473 
1474     if (filterType.isTableWise())
1475     {
1476         columnName = '*';
1477     }
1478 
1479     /**
1480      * @private
1481      */
1482     this.columnName = columnName;
1483 
1484     /**
1485      * @private
1486      */
1487     this.value = value;
1488 
1489     /**
1490      * @private
1491      */
1492     this.filterType = filterType;
1493 };
1494 
1495 /**
1496  * Gets the column name used in the filter.
1497  * @returns {String}
1498  */
1499 LABKEY.Query.Filter.prototype.getColumnName = function ()
1500 {
1501     return this.columnName
1502 };
1503 
1504 /**
1505  * Gets the filter type used to construct the filter.
1506  * @returns {LABKEY.Filter#Types}
1507  */
1508 LABKEY.Query.Filter.prototype.getFilterType = function ()
1509 {
1510     return this.filterType
1511 };
1512 
1513 /**
1514  * Returns the value of the filter.
1515  * @returns {*}
1516  */
1517 LABKEY.Query.Filter.prototype.getValue = function ()
1518 {
1519     return this.value
1520 };
1521 
1522 /**
1523  * Returns the value that will be put on URL.
1524  * @returns {String}
1525  */
1526 LABKEY.Query.Filter.prototype.getURLParameterValue = function ()
1527 {
1528     if (!this.filterType.isDataValueRequired())
1529         return '';
1530     if (LABKEY.Utils.isArray(this.value))
1531     {
1532         if (this.filterType === LABKEY.Filter.Types.IN || this.filterType === LABKEY.Filter.Types.NOT_IN)
1533         {
1534             var containsSemi = false;
1535             this.value.forEach(function (v) {
1536                 if (LABKEY.Utils.isString(v) && v.indexOf(';') !== -1) containsSemi = true;
1537             });
1538             if (containsSemi)
1539                 return "{json:" + JSON.stringify(this.value) + "}";
1540             else
1541                 return this.value.join(";");
1542         }
1543     }
1544     return this.value;
1545 };
1546 
1547 /**
1548  * Returns the URL parameter name used for the filter.
1549  * @param dataRegionName The dataRegionName the filter is associated with.
1550  * @returns {String}
1551  */
1552 LABKEY.Query.Filter.prototype.getURLParameterName = function (dataRegionName)
1553 {
1554     return (dataRegionName || "query") + "." + this.columnName + "~" + this.filterType.getURLSuffix();
1555 };
1556 
1557 LABKEY.Query.Filter.HasAnyValue = function (columnName)
1558 {
1559     LABKEY.Query.Filter.call(this, columnName, null, LABKEY.Filter.Types.HAS_ANY_VALUE);
1560 };
1561 LABKEY.Query.Filter.HasAnyValue.prototype = new LABKEY.Query.Filter;
1562 
1563 /**
1564  * @class LABKEY.Query.Filter.Equal subclass of {@link LABKEY.Query.Filter}.
1565  *      Finds rows where the column value matches the given filter value. Case-sensitivity depends upon how your
1566  *      underlying relational database was configured.
1567  * @augments LABKEY.Query.Filter
1568  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1569  * or a {@link LABKEY.FieldKey}
1570  * @param value Value used as the filter criterion or an Array of values.
1571  * @constructor
1572  */
1573 LABKEY.Query.Filter.Equal = function (columnName, value)
1574 {
1575     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.EQUAL);
1576 };
1577 LABKEY.Query.Filter.Equal.prototype = new LABKEY.Query.Filter;
1578 
1579 /**
1580  * @class LABKEY.Query.Filter.DateEqual subclass of {@link LABKEY.Query.Filter}.
1581  *      Finds rows where the date portion of a datetime column matches the filter value (ignoring the time portion).
1582  * @augments LABKEY.Query.Filter
1583  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1584  * or a {@link LABKEY.FieldKey}
1585  * @param value Value used as the filter criterion or an Array of values.
1586  * @constructor
1587  */
1588 LABKEY.Query.Filter.DateEqual = function (columnName, value)
1589 {
1590     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.DATE_EQUAL);
1591 };
1592 LABKEY.Query.Filter.DateEqual.prototype = new LABKEY.Query.Filter;
1593 
1594 /**
1595  * @class LABKEY.Query.Filter.DateNotEqual subclass of {@link LABKEY.Query.Filter}.
1596  *      Finds rows where the date portion of a datetime column does not match the filter value (ignoring the time portion).
1597  * @augments LABKEY.Query.Filter
1598  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1599  * or a {@link LABKEY.FieldKey}
1600  * @param value Value used as the filter criterion or an Array of values.
1601  * @constructor
1602  */
1603 LABKEY.Query.Filter.DateNotEqual = function (columnName, value)
1604 {
1605     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.DATE_NOT_EQUAL);
1606 };
1607 LABKEY.Query.Filter.DateNotEqual.prototype = new LABKEY.Query.Filter;
1608 
1609 /**
1610  * @class LABKEY.Query.Filter.NotEqualOrNull subclass of {@link LABKEY.Query.Filter}.
1611  *      Finds rows where the column value does not equal the filter value, or is missing (null).
1612  * @augments LABKEY.Query.Filter
1613  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1614  * or a {@link LABKEY.FieldKey}
1615  * @param value Value used as the filter criterion or an Array of values.
1616  * @constructor
1617  */
1618 LABKEY.Query.Filter.NotEqualOrNull = function (columnName, value)
1619 {
1620     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.NEQ_OR_NULL);
1621 };
1622 LABKEY.Query.Filter.NotEqualOrNull.prototype = new LABKEY.Query.Filter;
1623 
1624 /**
1625  * @class LABKEY.Query.Filter.NotEqualOrMissing subclass of {@link LABKEY.Query.Filter}.
1626  *      Finds rows where the column value does not equal the filter value, or is missing (null).
1627  * @augments LABKEY.Query.Filter
1628  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1629  * or a {@link LABKEY.FieldKey}
1630  * @param value Value used as the filter criterion or an Array of values.
1631  * @constructor
1632  */
1633 LABKEY.Query.Filter.NotEqualOrMissing = function (columnName, value)
1634 {
1635     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.NOT_EQUAL_OR_MISSING);
1636 };
1637 LABKEY.Query.Filter.NotEqualOrMissing.prototype = new LABKEY.Query.Filter;
1638 
1639 /**
1640  * @class LABKEY.Query.Filter.NotEqual subclass of {@link LABKEY.Query.Filter}.
1641  *      Finds rows where the column value does not equal the filter value.
1642  * @augments LABKEY.Query.Filter
1643  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1644  * or a {@link LABKEY.FieldKey}
1645  * @param value Value used as the filter criterion or an Array of values.
1646  * @constructor
1647  */
1648 LABKEY.Query.Filter.NotEqual = function (columnName, value)
1649 {
1650     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.NOT_EQUAL);
1651 };
1652 LABKEY.Query.Filter.NotEqual.prototype = new LABKEY.Query.Filter;
1653 
1654 /**
1655  * @class LABKEY.Query.Filter.Neq subclass of {@link LABKEY.Query.Filter}.
1656  *      Finds rows where the column value does not equal the filter value.
1657  * @augments LABKEY.Query.Filter
1658  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1659  * or a {@link LABKEY.FieldKey}
1660  * @param value Value used as the filter criterion or an Array of values.
1661  * @constructor
1662  */
1663 LABKEY.Query.Filter.Neq = function (columnName, value)
1664 {
1665     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.NEQ);
1666 };
1667 LABKEY.Query.Filter.Neq.prototype = new LABKEY.Query.Filter;
1668 
1669 /**
1670  * @class LABKEY.Query.Filter.Neq subclass of {@link LABKEY.Query.Filter}.
1671  *      Finds rows where the column value is blank.
1672  * @augments LABKEY.Query.Filter
1673  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1674  * or a {@link LABKEY.FieldKey}
1675  * @constructor
1676  */
1677 LABKEY.Query.Filter.IsBlank = function (columnName)
1678 {
1679     LABKEY.Query.Filter.call(this, columnName, null, LABKEY.Filter.Types.ISBLANK);
1680 };
1681 LABKEY.Query.Filter.IsBlank.prototype = new LABKEY.Query.Filter;
1682 
1683 /**
1684  * @class LABKEY.Query.Filter.Missing subclass of {@link LABKEY.Query.Filter}.
1685  *      Finds rows where the column value is missing (null). Note that no filter value is required with this operator.
1686  * @augments LABKEY.Query.Filter
1687  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1688  * or a {@link LABKEY.FieldKey}
1689  * @constructor
1690  */
1691 LABKEY.Query.Filter.Missing = function (columnName)
1692 {
1693     LABKEY.Query.Filter.call(this, columnName, null, LABKEY.Filter.Types.MISSING);
1694 };
1695 LABKEY.Query.Filter.Missing.prototype = new LABKEY.Query.Filter;
1696 
1697 /**
1698  * @class LABKEY.Query.Filter.NonBlank subclass of {@link LABKEY.Query.Filter}.
1699  *      Finds rows where the column value is not blank.
1700  * @augments LABKEY.Query.Filter
1701  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1702  * or a {@link LABKEY.FieldKey}
1703  * @constructor
1704  */
1705 LABKEY.Query.Filter.NonBlank = function (columnName)
1706 {
1707     LABKEY.Query.Filter.call(this, columnName, null, LABKEY.Filter.Types.NONBLANK);
1708 };
1709 LABKEY.Query.Filter.NonBlank.prototype = new LABKEY.Query.Filter;
1710 
1711 /**
1712  * @class LABKEY.Query.Filter.NotMissing subclass of {@link LABKEY.Query.Filter}.
1713  *      Finds rows where the column value is not missing.
1714  * @augments LABKEY.Query.Filter
1715  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1716  * or a {@link LABKEY.FieldKey}
1717  * @constructor
1718  */
1719 LABKEY.Query.Filter.NotMissing = function (columnName)
1720 {
1721     LABKEY.Query.Filter.call(this, columnName, null, LABKEY.Filter.Types.NOT_MISSING);
1722 };
1723 LABKEY.Query.Filter.NotMissing.prototype = new LABKEY.Query.Filter;
1724 
1725 /**
1726  * @class LABKEY.Query.Filter.Gt subclass of {@link LABKEY.Query.Filter}.
1727  *      Finds rows where the column value is greater than the filter value.
1728  * @augments LABKEY.Query.Filter
1729  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1730  * or a {@link LABKEY.FieldKey}
1731  * @param value Value used as the filter criterion or an Array of values.
1732  * @constructor
1733  */
1734 LABKEY.Query.Filter.Gt = function (columnName, value)
1735 {
1736     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.GT);
1737 };
1738 LABKEY.Query.Filter.Gt.prototype = new LABKEY.Query.Filter;
1739 
1740 /**
1741  * @class LABKEY.Query.Filter.GreaterThan subclass of {@link LABKEY.Query.Filter}.
1742  *      Finds rows where the column value is greater than the filter value.
1743  * @augments LABKEY.Query.Filter
1744  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1745  * or a {@link LABKEY.FieldKey}
1746  * @param value Value used as the filter criterion or an Array of values.
1747  * @constructor
1748  */
1749 LABKEY.Query.Filter.GreaterThan = function (columnName, value)
1750 {
1751     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.GREATER_THAN);
1752 };
1753 LABKEY.Query.Filter.GreaterThan.prototype = new LABKEY.Query.Filter;
1754 
1755 /**
1756  * @class LABKEY.Query.Filter.Lt subclass of {@link LABKEY.Query.Filter}.
1757  *      Finds rows where the column value is less than the filter value.
1758  * @augments LABKEY.Query.Filter
1759  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1760  * or a {@link LABKEY.FieldKey}
1761  * @param value Value used as the filter criterion or an Array of values.
1762  * @constructor
1763  */
1764 LABKEY.Query.Filter.Lt = function (columnName, value)
1765 {
1766     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.LT);
1767 };
1768 LABKEY.Query.Filter.Lt.prototype = new LABKEY.Query.Filter;
1769 
1770 /**
1771  * @class LABKEY.Query.Filter.LessThan subclass of {@link LABKEY.Query.Filter}.
1772  *      Finds rows where the column value is less than the filter value.
1773  * @augments LABKEY.Query.Filter
1774  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1775  * or a {@link LABKEY.FieldKey}
1776  * @param value Value used as the filter criterion or an Array of values.
1777  * @constructor
1778  */
1779 LABKEY.Query.Filter.LessThan = function (columnName, value)
1780 {
1781     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.LESS_THAN);
1782 };
1783 LABKEY.Query.Filter.LessThan.prototype = new LABKEY.Query.Filter;
1784 
1785 /**
1786  * @class LABKEY.Query.Filter.DateLessThan subclass of {@link LABKEY.Query.Filter}.
1787  *      Finds rows where the date portion of a datetime column is less than the filter value (ignoring the time portion).
1788  * @augments LABKEY.Query.Filter
1789  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1790  * or a {@link LABKEY.FieldKey}
1791  * @param value Value used as the filter criterion or an Array of values.
1792  * @constructor
1793  */
1794 LABKEY.Query.Filter.DateLessThan = function (columnName, value)
1795 {
1796     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.DATE_LESS_THAN);
1797 };
1798 LABKEY.Query.Filter.DateLessThan.prototype = new LABKEY.Query.Filter;
1799 
1800 /**
1801  * @class LABKEY.Query.Filter.Gte subclass of {@link LABKEY.Query.Filter}.
1802  *      Finds rows where the column value is greater than or equal to the filter value.
1803  * @augments LABKEY.Query.Filter
1804  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1805  * or a {@link LABKEY.FieldKey}
1806  * @param value Value used as the filter criterion or an Array of values.
1807  * @constructor
1808  */
1809 LABKEY.Query.Filter.Gte = function (columnName, value)
1810 {
1811     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.GTE);
1812 };
1813 LABKEY.Query.Filter.Gte.prototype = new LABKEY.Query.Filter;
1814 
1815 /**
1816  * @class LABKEY.Query.Filter.GreaterThanOrEqual subclass of {@link LABKEY.Query.Filter}.
1817  *      Finds rows where the column value is greater than or equal to the filter value.
1818  * @augments LABKEY.Query.Filter
1819  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1820  * or a {@link LABKEY.FieldKey}
1821  * @param value Value used as the filter criterion or an Array of values.
1822  * @constructor
1823  */
1824 LABKEY.Query.Filter.GreaterThanOrEqual = function (columnName, value)
1825 {
1826     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.GREATER_THAN_OR_EQUAL);
1827 };
1828 LABKEY.Query.Filter.GreaterThanOrEqual.prototype = new LABKEY.Query.Filter;
1829 
1830 /**
1831  * @class LABKEY.Query.Filter.GreaterThanOrEqual subclass of {@link LABKEY.Query.Filter}.
1832  *      Finds rows where the date portion of a datetime column is greater than or equal to the filter value
1833  *      (ignoring the time portion).
1834  * @augments LABKEY.Query.Filter
1835  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1836  * or a {@link LABKEY.FieldKey}
1837  * @param value Value used as the filter criterion or an Array of values.
1838  * @constructor
1839  */
1840 LABKEY.Query.Filter.DateGreaterThanOrEqual = function (columnName, value)
1841 {
1842     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.DATE_GREATER_THAN_OR_EQUAL);
1843 };
1844 LABKEY.Query.Filter.DateGreaterThanOrEqual.prototype = new LABKEY.Query.Filter;
1845 
1846 /**
1847  * @class LABKEY.Query.Filter.Lte subclass of {@link LABKEY.Query.Filter}.
1848  *      Finds rows where the column value is less than or equal to the filter value.
1849  * @augments LABKEY.Query.Filter
1850  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1851  * or a {@link LABKEY.FieldKey}
1852  * @param value Value used as the filter criterion or an Array of values.
1853  * @constructor
1854  */
1855 LABKEY.Query.Filter.Lte = function (columnName, value)
1856 {
1857     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.LTE);
1858 };
1859 LABKEY.Query.Filter.Lte.prototype = new LABKEY.Query.Filter;
1860 
1861 /**
1862  * @class LABKEY.Query.Filter.LessThanOrEqual subclass of {@link LABKEY.Query.Filter}.
1863  *      Finds rows where the column value is less than or equal to the filter value.
1864  * @augments LABKEY.Query.Filter
1865  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1866  * or a {@link LABKEY.FieldKey}
1867  * @param value Value used as the filter criterion or an Array of values.
1868  * @constructor
1869  */
1870 LABKEY.Query.Filter.LessThanOrEqual = function (columnName, value)
1871 {
1872     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.LESS_THAN_OR_EQUAL);
1873 };
1874 LABKEY.Query.Filter.LessThanOrEqual.prototype = new LABKEY.Query.Filter;
1875 
1876 /**
1877  * @class LABKEY.Query.Filter.DateLessThanOrEqual subclass of {@link LABKEY.Query.Filter}.
1878  *      Finds rows where the date portion of a datetime column is less than or equal to the filter value
1879  *      (ignoring the time portion).
1880  * @augments LABKEY.Query.Filter
1881  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1882  * or a {@link LABKEY.FieldKey}
1883  * @param value Value used as the filter criterion or an Array of values.
1884  * @constructor
1885  */
1886 LABKEY.Query.Filter.DateLessThanOrEqual = function (columnName, value)
1887 {
1888     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.DATE_LESS_THAN_OR_EQUAL);
1889 };
1890 LABKEY.Query.Filter.DateLessThanOrEqual.prototype = new LABKEY.Query.Filter;
1891 
1892 /**
1893  * @class LABKEY.Query.Filter.Contains subclass of {@link LABKEY.Query.Filter}.
1894  *      Finds rows where the column value contains the filter value. Note that this may result in a slow query as this
1895  *      cannot use indexes.
1896  * @augments LABKEY.Query.Filter
1897  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1898  * or a {@link LABKEY.FieldKey}
1899  * @param value Value used as the filter criterion or an Array of values.
1900  * @constructor
1901  */
1902 LABKEY.Query.Filter.Contains = function (columnName, value)
1903 {
1904     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.CONTAINS);
1905 };
1906 LABKEY.Query.Filter.Contains.prototype = new LABKEY.Query.Filter;
1907 
1908 /**
1909  * @class LABKEY.Query.Filter.DoesNotContain subclass of {@link LABKEY.Query.Filter}.
1910  *      Finds rows where the column value does not contain the filter value. Note that this may result in a slow query
1911  *      as this cannot use indexes.
1912  * @augments LABKEY.Query.Filter
1913  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1914  * or a {@link LABKEY.FieldKey}
1915  * @param value Value used as the filter criterion or an Array of values.
1916  * @constructor
1917  */
1918 LABKEY.Query.Filter.DoesNotContain = function (columnName, value)
1919 {
1920     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.DOES_NOT_CONTAIN);
1921 };
1922 LABKEY.Query.Filter.DoesNotContain.prototype = new LABKEY.Query.Filter;
1923 
1924 /**
1925  * @class LABKEY.Query.Filter.StartsWith subclass of {@link LABKEY.Query.Filter}.
1926  *      Finds rows where the column value starts with the filter value.
1927  * @augments LABKEY.Query.Filter
1928  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1929  * or a {@link LABKEY.FieldKey}
1930  * @param value Value used as the filter criterion or an Array of values.
1931  * @constructor
1932  */
1933 LABKEY.Query.Filter.StartsWith = function (columnName, value)
1934 {
1935     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.STARTS_WITH);
1936 };
1937 LABKEY.Query.Filter.StartsWith.prototype = new LABKEY.Query.Filter;
1938 
1939 /**
1940  * @class LABKEY.Query.Filter.In subclass of {@link LABKEY.Query.Filter}.
1941  *      Finds rows where the column value equals one of the supplied filter values. The values should be supplied as a
1942  *      semi-colon-delimited list (example usage: a;b;c).
1943  * @augments LABKEY.Query.Filter
1944  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1945  * or a {@link LABKEY.FieldKey}
1946  * @param value Value used as the filter criterion or an Array of values.
1947  * @constructor
1948  */
1949 LABKEY.Query.Filter.In = function (columnName, value)
1950 {
1951     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.IN);
1952 };
1953 LABKEY.Query.Filter.In.prototype = new LABKEY.Query.Filter;
1954 
1955 /**
1956  * @class LABKEY.Query.Filter.EqualsOneOf subclass of {@link LABKEY.Query.Filter}.
1957  *      Finds rows where the column value equals one of the supplied filter values. The values should be supplied as a
1958  *      semi-colon-delimited list (example usage: a;b;c).
1959  * @augments LABKEY.Query.Filter
1960  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1961  * or a {@link LABKEY.FieldKey}
1962  * @param value Value used as the filter criterion or an Array of values.
1963  * @constructor
1964  */
1965 LABKEY.Query.Filter.EqualsOneOf = function (columnName, value)
1966 {
1967     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.EQUALS_ONE_OF);
1968 };
1969 LABKEY.Query.Filter.EqualsOneOf.prototype = new LABKEY.Query.Filter;
1970 
1971 /**
1972  * @class LABKEY.Query.Filter.EqualsNoneOf subclass of {@link LABKEY.Query.Filter}.
1973  *      Finds rows where the column value does not equal one of the supplied filter values. The values should be supplied as a
1974  *      semi-colon-delimited list (example usage: a;b;c).
1975  * @augments LABKEY.Query.Filter
1976  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1977  * or a {@link LABKEY.FieldKey}
1978  * @param value Value used as the filter criterion or an Array of values.
1979  * @constructor
1980  */
1981 LABKEY.Query.Filter.EqualsNoneOf = function (columnName, value)
1982 {
1983     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.EQUALS_NONE_OF);
1984 };
1985 LABKEY.Query.Filter.EqualsNoneOf.prototype = new LABKEY.Query.Filter;
1986 
1987 /**
1988  * @class LABKEY.Query.Filter.NotIn subclass of {@link LABKEY.Query.Filter}.
1989  *      Finds rows where the column value is not in any of the supplied filter values. The values should be supplied as
1990  *      a semi-colon-delimited list (example usage: a;b;c).
1991  * @augments LABKEY.Query.Filter
1992  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
1993  * or a {@link LABKEY.FieldKey}
1994  * @param value Value used as the filter criterion or an Array of values.
1995  * @constructor
1996  */
1997 LABKEY.Query.Filter.NotIn = function (columnName, value)
1998 {
1999     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.NOT_IN);
2000 };
2001 LABKEY.Query.Filter.NotIn.prototype = new LABKEY.Query.Filter;
2002 
2003 /**
2004  * @class LABKEY.Query.Filter.ContainsOneOf subclass of {@link LABKEY.Query.Filter}.
2005  *      Finds rows where the column value contains any of the supplied filter values. The values should be supplied as a
2006  *      semi-colon-delimited list (example usage: a;b;c).
2007  * @augments LABKEY.Query.Filter
2008  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
2009  * or a {@link LABKEY.FieldKey}
2010  * @param value Value used as the filter criterion or an Array of values.
2011  * @constructor
2012  */
2013 LABKEY.Query.Filter.ContainsOneOf = function (columnName, value)
2014 {
2015     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.CONTAINS_ONE_OF);
2016 };
2017 LABKEY.Query.Filter.ContainsOneOf.prototype = new LABKEY.Query.Filter;
2018 
2019 /**
2020  * @class LABKEY.Query.Filter.MemberOf subclass of {@link LABKEY.Query.Filter}.
2021  *      Finds rows where the column value corresponds to a user that is a member of a group with the id of the supplied filter value.
2022  * @augments LABKEY.Query.Filter
2023  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
2024  * or a {@link LABKEY.FieldKey}
2025  * @param value Value used as the filter criterion.
2026  * @constructor
2027  */
2028 LABKEY.Query.Filter.MemberOf = function (columnName, value)
2029 {
2030     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.MEMBER_OF);
2031 };
2032 LABKEY.Query.Filter.ContainsOneOf.prototype = new LABKEY.Query.Filter;
2033 
2034 /**
2035  * @class LABKEY.Query.Filter.ContainsNoneOf subclass of {@link LABKEY.Query.Filter}.
2036  *      Finds rows where the column value does not contain any of the supplied filter values. The values should be supplied
2037  *      as a semi-colon-delimited list (example usage: a;b;c).
2038  * @augments LABKEY.Query.Filter
2039  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
2040  * or a {@link LABKEY.FieldKey}
2041  * @param value Value used as the filter criterion or an Array of values.
2042  * @constructor
2043  */
2044 LABKEY.Query.Filter.ContainsNoneOf = function (columnName, value)
2045 {
2046     LABKEY.Query.Filter.call(this, columnName, value, LABKEY.Filter.Types.CONTAINS_NONE_OF);
2047 };
2048 LABKEY.Query.Filter.ContainsNoneOf.prototype = new LABKEY.Query.Filter;
2049 
2050 /**
2051  * @class LABKEY.Query.Filter.HasMissingValue subclass of {@link LABKEY.Query.Filter}.
2052  *      Finds rows that have a missing value indicator.
2053  * @augments LABKEY.Query.Filter
2054  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
2055  * or a {@link LABKEY.FieldKey}
2056  * @constructor
2057  */
2058 LABKEY.Query.Filter.HasMissingValue = function (columnName)
2059 {
2060     LABKEY.Query.Filter.call(this, columnName, null, LABKEY.Filter.Types.HAS_MISSING_VALUE);
2061 };
2062 LABKEY.Query.Filter.HasMissingValue.prototype = new LABKEY.Query.Filter;
2063 
2064 /**
2065  * @class LABKEY.Query.Filter.DoesNotHaveMissingValue subclass of {@link LABKEY.Query.Filter}.
2066  *      Finds rows that do not have a missing value indicator.
2067  * @augments LABKEY.Query.Filter
2068  * @param columnName Required. The name of the column the filter will be applied to. Can be a string, array of strings,
2069  * or a {@link LABKEY.FieldKey}
2070  * @constructor
2071  */
2072 LABKEY.Query.Filter.DoesNotHaveMissingValue = function (columnName)
2073 {
2074     LABKEY.Query.Filter.call(this, columnName, null, LABKEY.Filter.Types.DOES_NOT_HAVE_MISSING_VALUE);
2075 };
2076 LABKEY.Query.Filter.DoesNotHaveMissingValue.prototype = new LABKEY.Query.Filter;
2077 
2078 (function(){
2079     /**
2080      * @class LABKEY.Query.Row The class used to wrap each row object returned from the server during a GetData, executeSql,
2081      * or selectRows request. Most users will not instantiate these themselves. Instead they will interact with them during
2082      * the success handler of the API they are using.
2083      * @see LABKEY.Query.Response
2084      * @param row The raw row from a GetData or executeSQL, selectRows (version 13.2 and above) request.
2085      * @constructor
2086      */
2087     LABKEY.Query.Row = function(row){
2088         this.links = null;
2089 
2090         if(row.links){
2091             this.links = row.links;
2092         }
2093 
2094         for (var attr in row.data) {
2095             if (row.data.hasOwnProperty(attr)) {
2096                 this[attr] = row.data[attr];
2097             }
2098         }
2099     };
2100 
2101     /**
2102      * Gets the requested column from the row. Includes extended values such as display value, URL, etc.
2103      * When requested version is >16.2, multi-value columns will return an array of objects containing "value" and other properties.
2104      * In the "17.1" format, "formattedValue" may be included in the response as the column display value formatted with the display column's format or folder format settings.
2105      * @param {String} columnName The column name requested. Used to do a case-insensitive match to find the column.
2106      * @returns {Object} For the given columnName, returns an object in the common case or an array of objects for multi-value columns.
2107      * The object will always contain a property named "value" that is the column's value, but it may also contain other properties about that column's value. For
2108      * example, if the column was setup to track missing value information, it will also contain a property named mvValue
2109      * (which is the raw value that is considered suspect), and a property named mvIndicator, which will be the string MV
2110      * indicator (e.g., "Q").
2111      */
2112     LABKEY.Query.Row.prototype.get = function(columnName){
2113         columnName = columnName.toLowerCase();
2114 
2115         for (var attr in this) {
2116             if (attr.toLowerCase() === columnName && this.hasOwnProperty(attr) && !(this[attr] instanceof Function)) {
2117                 return this[attr];
2118             }
2119         }
2120 
2121         return null;
2122     };
2123 
2124     /**
2125      * Gets the simple value for the requested column. Equivalent of doing Row.get(columnName).value.
2126      * For multi-value columns, the result is an array of values.
2127      * @param {String} columnName The column name requested. Used to do a case-insensitive match to find the column.
2128      * @returns {*} Returns the simple value for the given column.
2129      */
2130     LABKEY.Query.Row.prototype.getValue = function(columnName){
2131         columnName = columnName.toLowerCase();
2132 
2133         for (var attr in this) {
2134             if (attr.toLowerCase() === columnName && this.hasOwnProperty(attr) && !(this[attr] instanceof Function)) {
2135                 if (LABKEY.Utils.isArray(this[attr])) {
2136                     return this[attr].map(function (i) { return i.value; });
2137                 }
2138                 if (this[attr].hasOwnProperty('value')) {
2139                     return this[attr].value;
2140                 }
2141             }
2142         }
2143 
2144         return null;
2145     };
2146 
2147     /**
2148      * Gets all of the links for a row (details, update, etc.).
2149      * @returns {Object} Returns an object with all of the links types (details, update, etc.) for a row.
2150      */
2151     LABKEY.Query.Row.prototype.getLinks = function(){
2152         return this.links;
2153     };
2154 
2155     /**
2156      * Gets a specific link type for a row (details, update, etc.).
2157      * @param linkType Required. The name of the link type to be returned.
2158      * @returns {Object} Returns an object with the display text and link value.
2159      */
2160     LABKEY.Query.Row.prototype.getLink = function(linkType){
2161         if (this.links[linkType]) {
2162             return this.links[linkType];
2163         }
2164 
2165         return null;
2166     };
2167 
2168     /**
2169      * @private
2170      */
2171     var generateColumnModel = function(fields) {
2172         var i, columns = [];
2173 
2174         for (i = 0; i < fields.length; i++) {
2175             columns.push({
2176                 scale: fields[i].scale,
2177                 hidden: fields[i].hidden,
2178                 sortable: fields[i].sortable,
2179                 align: fields[i].align,
2180                 width: fields[i].width,
2181                 dataIndex: fields[i].fieldKey.toString(),
2182                 required: fields[i].nullable, // Not sure if this is correct.
2183                 editable: fields[i].userEditable,
2184                 header: fields[i].shortCaption
2185             })
2186         }
2187 
2188         return columns;
2189     };
2190 
2191     /**
2192      * @private
2193      */
2194     var generateGetDisplayField = function(fieldKeyToFind, fields) {
2195         return function() {
2196             var fieldString = fieldKeyToFind.toString();
2197             for (var i = 0; i < fields.length; i++) {
2198                 if (fieldString == fields[i].fieldKey.toString()) {
2199                     return fields[i];
2200                 }
2201             }
2202             return null;
2203         };
2204     };
2205 
2206     /**
2207      * @class The class used to wrap the response object from {@link LABKEY.Query.GetData.getRawData},
2208      *      {@link LABKEY.Query.selectRows}, and {@link LABKEY.Query.executeSql}.
2209      * @param response The raw JSON response object returned from the server when executing {@link LABKEY.Query.GetData.getRawData},
2210      *      {@link LABKEY.Query.selectRows}, or {@link LABKEY.Query.executeSql} when requiredVersion is greater than 13.2.
2211      * @see LABKEY.Query.GetData.getRawData
2212      * @see LABKEY.Query.selectRows
2213      * @see LABKEY.Query.executeSql
2214      * @constructor
2215      */
2216     LABKEY.Query.Response = function(response) {
2217         // response = response;
2218         var i, attr;
2219 
2220         // Shallow copy the response.
2221         for (attr in response) {
2222             if (response.hasOwnProperty(attr)) {
2223                 this[attr] = response[attr];
2224             }
2225         }
2226 
2227         // Wrap the Schema, Lookup, and Field Keys.
2228         this.schemaKey = LABKEY.SchemaKey.fromParts(response.schemaName);
2229 
2230         for (i = 0; i < response.metaData.fields.length; i++) {
2231             var field = response.metaData.fields[i],
2232                 lookup = field.lookup;
2233 
2234             field.fieldKey = LABKEY.FieldKey.fromParts(field.fieldKey);
2235 
2236             if (lookup && lookup.schemaName) {
2237                 lookup.schemaName = LABKEY.SchemaKey.fromParts(lookup.schemaName);
2238             }
2239 
2240             if (field.displayField) {
2241                 field.displayField = LABKEY.FieldKey.fromParts(field.displayField);
2242                 field.getDisplayField = generateGetDisplayField(field.displayField, response.metaData.fields);
2243             }
2244 
2245             // Only parse the 'extFormatFn' if ExtJS is present
2246             // checking to see if the fn ExtJS version and the window ExtJS version match
2247             if (field.extFormatFn) {
2248                 var ext4Index = field.extFormatFn.indexOf('Ext4.'),
2249                     isExt4Fn = ext4Index == 0 || ext4Index == 1,
2250                     canEvalExt3 = !isExt4Fn && window && window.Ext !== undefined,
2251                     canEvalExt4 = isExt4Fn && window && window.Ext4 !== undefined;
2252 
2253                 if (canEvalExt3 || canEvalExt4) {
2254                     field.extFormatFn = eval(field.extFormatFn);
2255                 }
2256             }
2257         }
2258 
2259         // Generate Column Model
2260         this.columnModel = generateColumnModel(this.metaData.fields);
2261 
2262         // Wrap the rows -- may not be in the response (e.g. maxRows: 0)
2263         if (this.rows !== undefined) {
2264             for (i = 0; i < this.rows.length; i++) {
2265                 this.rows[i] = new LABKEY.Query.Row(this.rows[i]);
2266             }
2267         }
2268         else {
2269             this.rows = [];
2270         }
2271 
2272         return this;
2273     };
2274 
2275     /**
2276      * Gets the metaData object from the response.
2277      * @returns {Object} Returns an object with the following properties:
2278      * <ul>
2279      *     <li><strong>fields</strong>: {Object[]}
2280      *     Each field has the following properties:
2281      *          <ul>
2282      *              <li><strong>name</strong>: {String} The name of the field</li>
2283      *              <li><strong>type</strong>: {String} JavaScript type name of the field</li>
2284      *              <li><strong>shownInInsertView</strong>: {Boolean} whether this field is intended to be shown in insert views</li>
2285      *              <li><strong>shownInUpdateView</strong>: {Boolean} whether this field is intended to be shown in update views</li>
2286      *              <li><strong>shownInDetailsView</strong>: {Boolean} whether this field is intended to be shown in details views</li>
2287      *              <li>
2288      *                  <strong>measure</strong>: {Boolean} whether this field is a measure.  Measures are fields that contain data
2289      *                  subject to charting and other analysis.
2290      *              </li>
2291      *              <li>
2292      *                  <strong>dimension</strong>: {Boolean} whether this field is a dimension.  Data dimensions define logical groupings
2293      *                  of measures.
2294      *              </li>
2295      *              <li><strong>hidden</strong>: {Boolean} whether this field is hidden and not normally shown in grid views</li>
2296      *              <li><strong>lookup</strong>: {Object} If the field is a lookup, there will
2297      *                  be four sub-properties listed under this property:
2298      *                  schema, table, displayColumn, and keyColumn, which describe the schema, table, and
2299      *                  display column, and key column of the lookup table (query).
2300      *              </li>
2301      *              <li>
2302      *                  <strong>displayField</strong>: {{@link LABKEY.FieldKey}} If the field has a display field this is
2303      *                  the field key for that field.
2304      *              </li>
2305      *              <li>
2306      *                  <strong>getDisplayField</strong>: {Function} If the field has a display field this function will
2307      *                  return the metadata field object for that field.
2308      *              </li>
2309      *          </ul>
2310      *     </li>
2311      *
2312      *     <li><strong>id</strong>: Name of the primary key column.</li>
2313      *     <li>
2314      *         <strong>root</strong>: Name of the property containing rows ("rows"). This is mainly for the Ext
2315      *         grid component.
2316      *     </li>
2317      *     <li><strong>title</strong>:</li>
2318      *     <li>
2319      *         <strong>totalProperty</strong>: Name of the top-level property containing the row count ("rowCount") in our case.
2320      *         This is mainly for the Ext grid component.
2321      *     </li>
2322      * </ul>
2323      */
2324     LABKEY.Query.Response.prototype.getMetaData = function() {
2325         return this.metaData;
2326     };
2327 
2328     /**
2329      * Returns the schema name from the Response.
2330      * @param {Boolean} asString
2331      * @returns {*} If asString is true it returns a string, otherwise it returns a {@link LABKEY.FieldKey} object.
2332      */
2333     LABKEY.Query.Response.prototype.getSchemaName = function(asString) {
2334         return asString ? this.schemaKey.toString() : this.schemaName;
2335     };
2336 
2337     /**
2338      * Returns the query name from the Response.
2339      * @returns {String}
2340      */
2341     LABKEY.Query.Response.prototype.getQueryName = function() {
2342         return this.queryName;
2343     };
2344 
2345     /**
2346      * Returns an array of objects that can be used to assist in creating grids using ExtJs.
2347      * @returns {Array} Returns an array of Objects that can be used to assist in creating Ext Grids to
2348      *      render the data.
2349      */
2350     LABKEY.Query.Response.prototype.getColumnModel = function() {
2351         return this.columnModel;
2352     };
2353 
2354     /**
2355      * Returns the array of row objects.
2356      * @returns {Array} Returns an array of {@link LABKEY.Query.Row} objects.
2357      */
2358     LABKEY.Query.Response.prototype.getRows = function() {
2359         return this.rows;
2360     };
2361 
2362     /**
2363      * Get a specific row from the row array.
2364      * @param {Integer} idx The index of the row you need.
2365      * @returns {LABKEY.Query.Row}
2366      */
2367     LABKEY.Query.Response.prototype.getRow = function(idx) {
2368         if (this.rows[idx] !== undefined) {
2369             return this.rows[idx];
2370         }
2371 
2372         throw new Error('No row found for index ' + idx);
2373     };
2374 
2375     /**
2376      * Gets the row count from the response, which is the total number of rows in the query, not necessarily the number
2377      * of rows returned. For example, if setting maxRows to 100 on a query that has 5,000 rows, getRowCount will return
2378      * 5,000, not 100.
2379      * @returns {Integer}
2380      */
2381     LABKEY.Query.Response.prototype.getRowCount = function() {
2382         return this.rowCount;
2383     };
2384 })();
2385 
2386 /**
2387 * @name LABKEY.Query.ModifyRowsOptions
2388 * @class   ModifyRowsOptions class to describe
2389             the third object passed to the successCallback function
2390             by {@link LABKEY.Query.updateRows}, {@link LABKEY.Query.insertRows} or
2391             {@link LABKEY.Query.deleteRows}. This object's properties are useful for
2392             matching requests to responses, as HTTP requests are typically
2393             processed asynchronously.
2394  *            <p>Additional Documentation:
2395  *              <ul>
2396  *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
2397  *                      How To Find schemaName, queryName & viewName</a></li>
2398  *              </ul>
2399  *           </p>
2400   * @see LABKEY.Query.updateRows
2401   * @see LABKEY.Query.insertRows
2402   * @see LABKEY.Query.deleteRows
2403 */
2404 
2405 /**#@+
2406 * @memberOf LABKEY.Query.ModifyRowsOptions#
2407 * @field
2408 */
2409 
2410 /**
2411 * @name headers
2412 * @description  An object containing one property for each HTTP header sent to the server.
2413 * @type Object
2414 */
2415 
2416 /**
2417 * @name method
2418 * @description The HTTP method used for the request (typically 'GET' or 'POST').
2419 * @type String
2420  */
2421 
2422 /**
2423 * @name url
2424 * @description  The URL that was requested.
2425 * @type String
2426 */
2427 
2428 /**
2429 * @name jsonData
2430 * @description  The data object sent to the server. This will contain the following properties:
2431           <ul>
2432             <li><b>schemaName</b>: String. The schema name being modified.  This is the same schemaName
2433                 the client passed to the calling function. </li>
2434             <li><b>queryName</b>: String. The query name being modified. This is the same queryName
2435                 the client passed to the calling function.  </li>
2436             <li><b>rows</b>: Object[]. Array of row objects that map the names of the row fields to their values.
2437             The fields required for inclusion for each row depend on the which LABKEY.Query method you are
2438             using (updateRows, insertRows or deleteRows). </li>
2439          </ul>
2440  <p/>
2441  <b>For {@link LABKEY.Query.updateRows}:</b> <p/>
2442  For the 'updateRows' method, each row in the rows array must include its primary key value
2443  as one of its fields.
2444  <p/>
2445  An example of a ModifyRowsOptions object for the 'updateRows' successCallback:
2446  <pre name="code" class="xml">
2447  {"schemaName": "lists",
2448   "queryName": "API Test List",
2449   "rows": [
2450  {"Key": 1,
2451  "FirstName": "Z",
2452  "Age": "100"}]
2453  } </pre></code>
2454 
2455  <p/>
2456  <b>For {@link LABKEY.Query.insertRows}:</b> <p/>
2457  For the 'insertRows' method, the fields of the rows should look the same as
2458  they do for the 'updateRows' method, except that primary key values for new rows
2459  need not be supplied if the primary key columns are auto-increment.
2460  <p/>
2461  An example of a ModifyRowsOptions object for the 'insertRows' successCallback:
2462  <pre name="code" class="xml">
2463  {"schemaName": "lists",
2464   "queryName": "API Test List",
2465   "rows": [
2466   {"FirstName": "C",
2467  "Age": "30"}]
2468  } </pre></code>
2469 
2470  <p/>
2471  <b>For {@link LABKEY.Query.deleteRows}:</b> <p/>
2472  For the 'deleteRows' method, the fields of the rows should look the
2473  same as they do for the 'updateRows' method, except that the 'deleteRows'
2474  method needs to supply only the primary key values for the rows. All
2475  other row data will be ignored.
2476  <p/>
2477  An example of a ModifyRowsOptions object for the 'deleteRows' successCallback:
2478  <pre name="code" class="xml">
2479  {"schemaName": "lists",
2480   "queryName": "API Test List",
2481   "rows": [
2482 {"Key": 3}]
2483  } </pre></code>
2484 * @type  Object
2485 */
2486 
2487 /**#@-*/
2488 
2489  /**
2490 * @name LABKEY.Query.ModifyRowsResults
2491 * @class  ModifyRowsResults class to describe
2492             the first object passed to the successCallback function
2493             by {@link LABKEY.Query.updateRows}, {@link LABKEY.Query.insertRows} or
2494             {@link LABKEY.Query.deleteRows}. This object's properties are useful for
2495             matching requests to responses, as HTTP requests are typically
2496             processed asynchronously.
2497   *            <p>Additional Documentation:
2498   *              <ul>
2499   *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
2500   *                      How To Find schemaName, queryName & viewName</a></li>
2501   *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=javascriptTutorial">LabKey JavaScript API Tutorial</a> and
2502   *                      <a href="https://www.labkey.org/home/Study/demo/wiki-page.view?name=reagentRequest">Demo</a></li>
2503   *              </ul>
2504   *           </p>
2505 * @example For example:
2506         <pre name="code" class="xml">
2507         {  "schemaName": "lists",
2508            "queryName": "API Test List"
2509            "rowsAffected": 1,
2510            "command": "insert",
2511            "errors": [],
2512            "rows": [{ Key: 3, StringField: 'NewValue'}]
2513         } </pre></code>
2514 * @see LABKEY.Query.updateRows
2515 * @see LABKEY.Query.insertRows
2516 * @see LABKEY.Query.deleteRows
2517 * @see LABKEY.Query.saveRows
2518 */
2519 
2520 /**#@+
2521 * @memberOf LABKEY.Query.ModifyRowsResults#
2522 * @field
2523 */
2524 
2525 /**
2526 * @name LABKEY.Query.ModifyRowsResults#schemaName
2527 * @description  Contains the same schemaName the client passed to the calling function.
2528 * @type  String
2529 */
2530 
2531 /**
2532 * @name     LABKEY.Query.ModifyRowsResults#queryName
2533 * @description  Contains the same queryName the client passed to the calling function.
2534 * @type     String
2535 */
2536 
2537 /**
2538 * @name    command
2539 * @description   Will be "update", "insert", or "delete" depending on the API called.
2540 * @type    String
2541 */
2542 
2543 /**
2544 * @name    errors
2545 * @description   Objects will contain the properties 'id' (the field to which the error is related, if any),
2546 *                and 'msg' (the error message itself).
2547 * @type    Array
2548 */
2549 
2550 /**
2551 * @name  rowsAffected
2552 * @description  Indicates the number of rows affected by the API action.
2553             This will typically be the same number of rows passed in to the calling function.
2554 * @type        Integer
2555 */
2556 
2557 /**
2558 * @name LABKEY.Query.ModifyRowsResults#rows
2559 * @description   Array of rows with field values for the rows updated, inserted,
2560             or deleted, in the same order as the rows supplied in the request. For insert, the
2561             new key value for an auto-increment key will be in the returned row's field values.
2562             For insert or update, the other field values may also be different than those supplied
2563             as a result of database default expressions, triggers, or LabKey's automatic tracking
2564             feature, which automatically adjusts columns of certain names (e.g., Created, CreatedBy,
2565             Modified, ModifiedBy, etc.).
2566 * @type    Object[]
2567 */
2568 
2569 /**#@-*/
2570 
2571 /**
2572 * @name LABKEY.Query.SelectRowsOptions
2573 * @class  SelectRowsOptions class to describe
2574            the third object passed to the successCallback function by
2575            {@link LABKEY.Query.selectRows}.  This object's properties are useful for
2576            matching requests to responses, as HTTP requests are typically
2577            processed asynchronously.
2578  *            <p>Additional Documentation:
2579  *              <ul>
2580  *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
2581  *                      How To Find schemaName, queryName & viewName</a></li>
2582  *              </ul>
2583  *           </p>
2584 * @see LABKEY.Query.selectRows
2585 */
2586 
2587 /**#@+
2588 * @memberOf LABKEY.Query.SelectRowsOptions#
2589 * @field
2590 */
2591 
2592 /**
2593 * @name   query.schemaName
2594 * @description   Contains the same schemaName the client passed to the
2595             calling function. See <a class="link"
2596             href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
2597             How To Find schemaName, queryName & viewName</a>.
2598 * @type   String
2599 */
2600 
2601 /**
2602 * @name   query.queryName
2603 * @description   Contains the same queryName the client passed
2604             to the calling function. See
2605             <a href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
2606             How To Find schemaName, queryName & viewName</a>.
2607 * @type   String
2608 */
2609 
2610 /**
2611 * @name    query.viewName
2612 * @description 	Name of a valid custom view for the chosen queryName. See
2613             <a href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
2614             How To Find schemaName, queryName & viewName</a>.
2615 * @type    String
2616 */
2617 
2618 /**
2619 * @name    query.offset
2620 * @description  Row number at which results should begin.
2621             Use this with maxRows to get pages of results.
2622 * @type   Integer
2623 */
2624 
2625 /**
2626 * @name   query.sort
2627 * @description	Sort specification. This can be a comma-delimited list of
2628             column names, where each column may have an optional dash (-) before the name
2629             to indicate a descending sort.
2630 * @type  String
2631 */
2632 
2633 /**
2634 * @name   maxRows
2635 * @description   Maximum number of rows to return
2636 * @type     Integer
2637 */
2638 
2639 /**
2640 * @name   filters
2641 * @description   An object whose properties are filter specifications, one for each filter you supplied.
2642  *          All filters are combined using AND logic. Each one is of type {@link LABKEY.Filter.FilterDefinition}.
2643  *          The list of valid operators:
2644             <ul><li><b>eq</b> = equals</li>
2645             <li><b>neq</b> = not equals</li>
2646             <li><b>gt</b> = greater-than</li>
2647             <li><b>gte</b> = greater-than or equal-to</li>
2648             <li><b>lt</b> = less-than</li>
2649             <li><b>lte</b> = less-than or equal-to</li>
2650             <li><b>dateeq</b> = date equal</li>
2651             <li><b>dateneq</b> = date not equal</li>
2652             <li><b>neqornull</b> = not equal or null</li>
2653             <li><b>isblank</b> = is null</li>
2654             <li><b>isnonblank</b> = is not null</li>
2655             <li><b>contains</b> = contains</li>
2656             <li><b>doesnotcontain</b> = does not contain</li>
2657             <li><b>startswith</b> = starts with</li>
2658             <li><b>doesnotstartwith</b> = does not start with</li>
2659             <li><b>in</b> = equals one of</li></ul>
2660 * @type    Object
2661 */
2662 
2663 /**#@-*/
2664 
2665 /**
2666 * @name LABKEY.Query.FieldMetaDataLookup
2667 * @class  Lookup metadata about a single field.
2668  *            <p>Additional Documentation:
2669  *              <ul>
2670  *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
2671  *                      How To Find schemaName, queryName & viewName</a></li>
2672  *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=javascriptTutorial">LabKey JavaScript API Tutorial</a> and
2673  *                      <a href="https://www.labkey.org/home/Study/demo/wiki-page.view?name=reagentRequest">Demo</a></li>
2674  *              </ul>
2675  *           </p>
2676  * @see LABKEY.Query.FieldMetaData
2677 */
2678 
2679 /**#@+
2680 * @memberOf LABKEY.Query.FieldMetaDataLookup#
2681 * @field
2682 * @name    containerPath
2683 * @description The path to the container that this lookup points to, if not the current container
2684 * @type    String
2685 */
2686 
2687 /**#@+
2688 * @memberOf LABKEY.Query.FieldMetaDataLookup#
2689 * @field
2690 * @name    public
2691 * @description Whether the target of this lookup is exposed as a top-level query
2692 * @type    boolean
2693 */
2694 
2695 /**#@+
2696 * @memberOf LABKEY.Query.FieldMetaDataLookup#
2697 * @field
2698 * @name queryName
2699 * @description The name of the query that this lookup targets
2700 * @type    String
2701 */
2702 
2703 /**#@+
2704 * @memberOf LABKEY.Query.FieldMetaDataLookup#
2705 * @field
2706 * @name schemaName
2707 * @description The name of the schema that this lookup targets
2708 * @type    String
2709 */
2710 
2711 /**#@+
2712 * @memberOf LABKEY.Query.FieldMetaDataLookup#
2713 * @field
2714 * @name keyColumn
2715 * @description The name of column in the lookup's target that will be joined to the value in the local field
2716 * @type    String
2717 */
2718 
2719 /**#@+
2720 * @memberOf LABKEY.Query.FieldMetaDataLookup#
2721 * @field
2722 * @name displayColumn
2723 * @description The name of the column in the lookup's target that will be shown as its value, instead of the raw key value
2724 * @type    String
2725 */
2726 
2727 /**#@-*/
2728 
2729 /**
2730 * @name LABKEY.Query.FieldMetaData
2731 * @class  Metadata about a single field.
2732  *            <p>Additional Documentation:
2733  *              <ul>
2734  *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
2735  *                      How To Find schemaName, queryName & viewName</a></li>
2736  *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=javascriptTutorial">LabKey JavaScript API Tutorial</a> and
2737  *                      <a href="https://www.labkey.org/home/Study/demo/wiki-page.view?name=reagentRequest">Demo</a></li>
2738  *              </ul>
2739  *           </p>
2740  * @see LABKEY.Query.selectRows
2741  * @see LABKEY.Query.getQueryDetails
2742 */
2743 
2744 /**#@+
2745 * @memberOf LABKEY.Query.FieldMetaData#
2746 * @field
2747 * @name    name
2748 * @description The name of the field
2749 * @type    String
2750 */
2751 
2752 /**#@+
2753 * @memberOf LABKEY.Query.FieldMetaData#
2754 * @field
2755 * @name    friendlyType
2756 * @description A friendlier, more verbose description of the type, like "Text (String)" or "Date and Time"
2757 * @type    String
2758 */
2759 
2760 /**#@+
2761 * @memberOf LABKEY.Query.FieldMetaData#
2762 * @field
2763 * @name    shownInInsertView
2764 * @description Whether this field is intended to be displayed in insert UIs
2765 * @type    boolean
2766 */
2767 
2768 /**#@+
2769 * @memberOf LABKEY.Query.FieldMetaData#
2770 * @field
2771 * @name    shownInDetailView
2772 * @description Whether this field is intended to be displayed in detail UIs
2773 * @type    boolean
2774 */
2775 
2776 /**#@+
2777 * @memberOf LABKEY.Query.FieldMetaData#
2778 * @field
2779 * @name    shownInUpdateView
2780 * @description Whether this field is intended to be displayed in update UIs
2781 * @type    boolean
2782 */
2783 
2784 /**#@+
2785 * @memberOf LABKEY.Query.FieldMetaData#
2786 * @field
2787 * @name    versionField
2788 * @description Whether this field's value stores version information for the row
2789 * @type    boolean
2790 */
2791 
2792 /**#@+
2793 * @memberOf LABKEY.Query.FieldMetaData#
2794 * @field
2795 * @name userEditable
2796 * @description Whether this field is intended to be edited directly by the user, or managed by the system
2797 * @type    boolean
2798 */
2799 
2800 /**#@+
2801 * @memberOf LABKEY.Query.FieldMetaData#
2802 * @field
2803 * @name calculated
2804 * @description Whether this field is a calculated value such as something generated by a SQL expression,
2805 * or a "real"/"physical" column in the database
2806 * @type    boolean
2807 */
2808 
2809 /**#@+
2810 * @memberOf LABKEY.Query.FieldMetaData#
2811 * @field
2812 * @name readOnly
2813 * @description Whether the field's value can be modified
2814 * @type    boolean
2815 */
2816 
2817 /**#@+
2818 * @memberOf LABKEY.Query.FieldMetaData#
2819 * @field
2820 * @name nullable
2821 * @description Whether the field's value is allowed to be null
2822 * @type    boolean
2823 */
2824 
2825 /**#@+
2826 * @memberOf LABKEY.Query.FieldMetaData#
2827 * @field
2828 * @name mvEnabled
2829 * @description Whether this field supports missing value indicators instead of or addition to its standard value
2830 * @type    boolean
2831 */
2832 
2833 /**#@+
2834 * @memberOf LABKEY.Query.FieldMetaData#
2835 * @field
2836 * @name keyField
2837 * @description Whether this field is part of the row's primary key
2838 * @type    boolean
2839 */
2840 
2841 /**#@+
2842 * @memberOf LABKEY.Query.FieldMetaData#
2843 * @field
2844 * @name hidden
2845 * @description Whether this value is intended to be hidden from the user, especially for grid views
2846 * @type    boolean
2847 */
2848 
2849 /**#@+
2850 * @memberOf LABKEY.Query.FieldMetaData#
2851 * @field
2852 * @name autoIncrement
2853 * @description Whether this field's value is automatically assigned by the server, like a RowId whose value is determined by a database sequence
2854 * @type    boolean
2855 */
2856 
2857 /**#@+
2858 * @memberOf LABKEY.Query.FieldMetaData#
2859 * @field
2860 * @name jsonType
2861 * @description The type of JSON object that will represent this field's value: string, boolean, date, int, or float
2862 * @type    String
2863 */
2864 
2865 /**#@+
2866 * @memberOf LABKEY.Query.FieldMetaData#
2867 * @field
2868 * @name importAliases
2869 * @description Alternate names for this field that may appear in data when importing, whose values should be mapped to this field
2870 * @type    String[]
2871 */
2872 
2873 /**#@+
2874 * @memberOf LABKEY.Query.FieldMetaData#
2875 * @field
2876 * @name tsvFormat
2877 * @description The format string to be used for TSV exports
2878 * @type    String
2879 */
2880 
2881 /**#@+
2882 * @memberOf LABKEY.Query.FieldMetaData#
2883 * @field
2884 * @name format
2885 * @description The format string to be used for generating HTML
2886 * @type    String
2887 */
2888 
2889 /**#@+
2890 * @memberOf LABKEY.Query.FieldMetaData#
2891 * @field
2892 * @name excelFormat
2893 * @description The format string to be used for Excel exports
2894 * @type    String
2895 */
2896 
2897 /**#@+
2898 * @memberOf LABKEY.Query.FieldMetaData#
2899 * @field
2900 * @name extFormat
2901 * @description The format string that can be passed to Ext components.  This is currently only supported for dates.
2902 * @type    String
2903 */
2904 
2905 /**#@+
2906 * @memberOf LABKEY.Query.FieldMetaData#
2907 * @field
2908 * @name extFormatFn
2909 * @description A function that can be used to produce the formatted string for this field.  This is currently supported for dates and numeric values.
2910 * Note: this function is returned as a string, so you will need to evaluate it to convert it to a function.  See example below.
2911 * @example <pre name="code" class="xml">
2912 * var formatFn = eval(meta.extFormatFn);
2913 * var formattedValue = formatFn(data);
2914 * </pre></code>
2915 *
2916 * @type    String
2917 */
2918 
2919 /**#@+
2920 * @memberOf LABKEY.Query.FieldMetaData#
2921 * @field
2922 * @name caption
2923 * @description The caption to be shown for this field, typically in a column header, which may differ from its name
2924 * @type    String
2925 */
2926 
2927 /**#@+
2928 * @memberOf LABKEY.Query.FieldMetaData#
2929 * @field
2930 * @name shortCaption
2931 * @description The caption for this field, without any prefix from potential parent lookups. In many cases this will be identical to the caption property.
2932 * @type    String
2933 */
2934 
2935 /**#@+
2936 * @memberOf LABKEY.Query.FieldMetaData#
2937 * @field
2938 * @name description
2939 * @description The description for this field
2940 * @type    String
2941 */
2942 
2943 /**#@+
2944 * @memberOf LABKEY.Query.FieldMetaData#
2945 * @field
2946 * @name inputType
2947 * @description The type of form input to be used when editing this field, such as select, text, textarea, checkbox, or file
2948 * @type    boolean
2949 */
2950 
2951 /**#@+
2952 * @memberOf LABKEY.Query.FieldMetaData#
2953 * @field
2954 * @name lookup
2955 * @description Information about this field's lookup configuration
2956 * @type    LABKEY.Query.FieldMetaDataLookup
2957 */
2958 
2959 /**#@-*/
2960 
2961 /**
2962 * @name LABKEY.Query.SelectRowsResults
2963 * @class  SelectRowsResults class to describe the first
2964             object passed to the successCallback function by
2965             {@link LABKEY.Query.selectRows}. This object's properties are useful for
2966             matching requests to responses, as HTTP requests are typically
2967             processed asynchronously.
2968  *            <p>Additional Documentation:
2969  *              <ul>
2970  *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
2971  *                      How To Find schemaName, queryName & viewName</a></li>
2972  *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=javascriptTutorial">LabKey JavaScript API Tutorial</a> and
2973  *                      <a href="https://www.labkey.org/home/Study/demo/wiki-page.view?name=reagentRequest">Demo</a></li>
2974  *              </ul>
2975  *           </p>
2976 * @see LABKEY.Query.selectRows
2977 */
2978 
2979 /**#@+
2980 * @memberOf LABKEY.Query.SelectRowsResults#
2981 * @field
2982 */
2983 
2984 /**
2985 * @name    schemaName
2986 * @description the name of the resultset's source schema.
2987 * @type    String
2988 */
2989 
2990 /**
2991 * @name    queryName
2992 * @description the name of the resultset's source query.  In some cases, such as an 'executeSql' call with 'saveInSession' set to true, the
2993  * query name may refer to temporary query that can be used to re-retrieve data for the duration of the user's session. 
2994 * @type    String
2995 */
2996 
2997 /**
2998 * @name    metaData
2999 * @description Contains type and lookup information about the columns in the resultset.
3000 * @type    Object
3001 */
3002 
3003 /**
3004 * @name    metaData.root
3005 * @description 	Name of the property containing rows ("rows"). This is mainly for the Ext grid component.
3006 * @type     String
3007 */
3008 
3009 /**
3010 * @name    metaData.totalProperty
3011 * @description 	Name of the top-level property
3012             containing the row count ("rowCount") in our case. This is mainly
3013             for the Ext grid component.
3014 * @type   String
3015 */
3016 
3017 /**
3018 * @name   metaData.sortInfo
3019 * @description  Sort specification in Ext grid terms.
3020             This contains two sub-properties, field and direction, which indicate
3021             the sort field and direction ("ASC" or "DESC") respectively.
3022 * @type   Object
3023 */
3024 
3025 /**
3026 * @name    metaData.id
3027 * @description  Name of the primary key column.
3028 * @type     String
3029 */
3030 
3031 /**
3032 * @name    metaData.fields
3033 * @description	Array of field information.
3034 * @type    LABKEY.Query.FieldMetaData[]
3035 */
3036 
3037 /**
3038 * @name    columnModel
3039 * @description   Contains information about how one may interact
3040             with the columns within a user interface. This format is generated
3041             to match the requirements of the Ext grid component. See
3042             <a href="http://extjs.com/deploy/ext-2.2.1/docs/?class=Ext.grid.ColumnModel">
3043             Ext.grid.ColumnModel</a> for further information.
3044 * @type  Object[]
3045 */
3046 
3047 /**
3048 * @name   rows
3049 * @description    An array of rows, each of which is a
3050             sub-element/object containing a property per column.
3051 * @type   Object[]
3052 */
3053 
3054 /**
3055 * @name rowCount
3056 * @description Indicates the number of total rows that could be
3057             returned by the query, which may be more than the number of objects
3058             in the rows array if the client supplied a value for the query.maxRows
3059             or query.offset parameters. This value is useful for clients that wish
3060             to display paging UI, such as the Ext grid.
3061 * @type   Integer
3062 */
3063 
3064 /**#@-*/
3065 
3066  /**
3067 * @name LABKEY.Query.ExtendedSelectRowsResults
3068 * @class  ExtendedSelectRowsResults class to describe the first
3069             object passed to the successCallback function by
3070             {@link LABKEY.Query.selectRows} if config.requiredVersion is set to "9.1".
3071   *            <p>Additional Documentation:
3072   *              <ul>
3073   *                  <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=findNames">
3074   *                      How To Find schemaName, queryName & viewName</a></li>
3075   *              </ul>
3076   *           </p>
3077 * @see LABKEY.Query.selectRows
3078  */
3079 
3080 /**#@+
3081 * @memberOf LABKEY.Query.ExtendedSelectRowsResults#
3082 * @field
3083 */
3084 
3085 /**
3086 * @name    LABKEY.Query.ExtendedSelectRowsResults#metaData
3087 * @description Contains type and lookup information about the columns in the resultset.
3088 * @type    Object
3089 */
3090 
3091 /**
3092 * @name    LABKEY.Query.ExtendedSelectRowsResults#metaData.root
3093 * @description 	Name of the property containing rows ("rows"). This is mainly for the Ext grid component.
3094 * @type     String
3095 */
3096 
3097 /**
3098 * @name    LABKEY.Query.ExtendedSelectRowsResults#metaData.totalProperty
3099 * @description 	Name of the top-level property
3100             containing the row count ("rowCount") in our case. This is mainly
3101             for the Ext grid component.
3102 * @type   String
3103 */
3104 
3105 /**
3106 * @name   LABKEY.Query.ExtendedSelectRowsResults#metaData.sortInfo
3107 * @description  Sort specification in Ext grid terms.
3108             This contains two sub-properties, field and direction, which indicate
3109             the sort field and direction ("ASC" or "DESC") respectively.
3110 * @type   Object
3111 */
3112 
3113 /**
3114 * @name    LABKEY.Query.ExtendedSelectRowsResults#metaData.id
3115 * @description  Name of the primary key column.
3116 * @type     String
3117 */
3118 
3119 /**
3120 * @name    LABKEY.Query.ExtendedSelectRowsResults#metaData.fields
3121 * @description	Array of field information.
3122             Each field has the following properties:
3123             <ul><li><b>name</b> -- The name of the field</li>
3124             <li><b>type</b> -- JavaScript type name of the field</li>
3125             <li><b>shownInInsertView</b> -- whether this field is intended to be shown in insert views</li>
3126             <li><b>shownInUpdateView</b> -- whether this field is intended to be shown in update views</li>
3127             <li><b>shownInDetailsView</b> -- whether this field is intended to be shown in details views</li>
3128             <li><b>measure</b> -- whether this field is a measure.  Measures are fields that contain data subject to charting and other analysis.</li>
3129             <li><b>dimension</b> -- whether this field is a dimension.  Data dimensions define logical groupings of measures.</li>
3130             <li><b>hidden</b> -- whether this field is hidden and not normally shown in grid views</li>
3131             <li><b>lookup</b> -- If the field is a lookup, there will
3132                 be four sub-properties listed under this property:
3133                 schema, table, displayColumn, and keyColumn, which describe the schema, table, and
3134                 display column, and key column of the lookup table (query).</li></ul>
3135 * @type    Object[]
3136 */
3137 
3138 /**
3139 * @name    LABKEY.Query.ExtendedSelectRowsResults#columnModel
3140 * @description   Contains information about how one may interact
3141             with the columns within a user interface. This format is generated
3142             to match the requirements of the Ext grid component. See
3143             <a href="http://extjs.com/deploy/ext-2.2.1/docs/?class=Ext.grid.ColumnModel">
3144             Ext.grid.ColumnModel</a> for further information.
3145 * @type  String
3146 */
3147 
3148 /**
3149 * @name   LABKEY.Query.ExtendedSelectRowsResults#rows
3150 * @description    An array of rows, each of which is a
3151             sub-element/object containing an object per column. The
3152             object will always contain a property named "value" that is the
3153             column's value, but it may also contain other properties about
3154             that column's value. For example, if the column was setup to track
3155             missing value information, it will also contain a property named mvValue (which
3156             is the raw value that is considered suspect), and a property named
3157             mvIndicator, which will be the string MV indicator (e.g., "Q").
3158 * @type   Object[]
3159 */
3160 
3161 /**
3162 * @name LABKEY.Query.ExtendedSelectRowsResults#rowCount
3163 * @description Indicates the number of total rows that could be
3164             returned by the query, which may be more than the number of objects
3165             in the rows array if the client supplied a value for the query.maxRows
3166             or query.offset parameters. This value is useful for clients who wish
3167             to display paging UI, such as the Ext grid.
3168 * @type   Integer
3169 */
3170 
3171 /**#@-*/
3172 
3173 /** docs for methods defined in dom/Query.js - primarily here to ensure API docs get generated with combined core/dom versions */
3174 
3175 /**
3176  * Execute arbitrary LabKey SQL and export the results to Excel or TSV. After this method is
3177  * called, the user will be prompted to accept a file from the server, and most browsers will allow
3178  * the user to either save it or open it in an appropriate application.
3179  * For more information, see the
3180  * <a href="https://www.labkey.org/Documentation/wiki-page.view?name=labkeySql">
3181  * LabKey SQL Reference</a>.
3182  *
3183  * @memberOf LABKEY.Query
3184  * @function
3185  * @static
3186  * @name exportSql
3187  * @param config An object which contains the following configuration properties.
3188  * @param {String} config.schemaName name of the schema to query.
3189  * @param {String} config.sql The LabKey SQL to execute.
3190  * @param {String} [config.format] The desired export format. May be either 'excel' or 'tsv'. Defaults to 'excel'.
3191  * @param {String} [config.containerPath] The path to the container in which the schema and query are defined,
3192  *       if different than the current container. If not supplied, the current container's path will be used.
3193  * @param {String} [config.containerFilter] One of the values of {@link LABKEY.Query.containerFilter} that sets
3194  *       the scope of this query. Defaults to containerFilter.current, and is interpreted relative to
3195  *       config.containerPath.
3196  */
3197 
3198 /**
3199  * Load the set of user visible schemas from the given container into a standard <select> input element.
3200  *
3201  * @memberOf LABKEY.Query
3202  * @function
3203  * @static
3204  * @name schemaSelectInput
3205  * @param config An object which contains the following configuration properties.
3206  * @param {String} config.renderTo the id of the <select> input to load the LabKey queries into.
3207  * @param {String} config.initValue the initial value to try and set the <select> element value after it loads.
3208  */
3209 
3210 /**
3211  * Load the set of queries from this container for a given schema into a standard <select> input. The config object
3212  * must define which <select> input is for the schemas and which <select> input is for the queries. This function
3213  * also then associates the two <select> inputs so that a selection change in the schema input will update the
3214  * query input accordingly.
3215  *
3216  * @memberOf LABKEY.Query
3217  * @function
3218  * @static
3219  * @name querySelectInput
3220  * @param config An object which contains the following configuration properties.
3221  * @param {String} config.renderTo the id of the <select> input to load the LabKey queries into.
3222  * @param {String} config.schemaInputId the id of the <select> input to load the LabKey schemas into.
3223  * @param {String} config.initValue the initial value to try and set the <select> element value after it loads.
3224  */
3225 
3226 /**
3227  * Load the set of columns for a given schema/query into a standard <select> input. The config object
3228  * must define the schemaName and queryName to be used to source the column listing.
3229  *
3230  * @memberOf LABKEY.Query
3231  * @function
3232  * @static
3233  * @name columnSelectInput
3234  * @param config An object which contains the following configuration properties.
3235  * @param {String} config.renderTo the id of the <select> input to load the LabKey queries into. Required.
3236  * @param {String} config.schemaName the name of the schema. Required.
3237  * @param {String} config.queryName the name of the query. Required.
3238  * @param {String} config.initValue the initial value to try and set the <select> element value after it loads. Optional.
3239  * @param {String} config.filterFn a function to call to filter the column set (ex. by data type). Optional.
3240  * @param {String} config.sortFn a function to call to sort the column set. Optional.
3241  */
3242 
3243 /**
3244  * Load the set of views for a given schema/query into a standard <select> input. The config object
3245  * must define which <select> input is for the schemas and which <select> input is for the queries. This function
3246  * also then associates the two <select> inputs so that a selection change in the query input will update the
3247  * views input accordingly.
3248  *
3249  * @memberOf LABKEY.Query
3250  * @function
3251  * @static
3252  * @name queryViewSelectInput
3253  * @param config An object which contains the following configuration properties.
3254  * @param {String} config.renderTo the id of the <select> input to load the LabKey query views into. Required.
3255  * @param {String} config.schemaInputId the name of the <select> input to pull the LabKey schema from.
3256  * @param {String} config.queryInputId the name of the <select> input to load the LabKey query from.
3257  * @param {String} config.initValue the initial value to try and set the <select> element value after it loads. Optional.
3258  */
3259 
3260 /**
3261  * Bulk import data rows into a table.
3262  * One of 'text', 'path', 'moduleResource', or 'file' is required and cannot be combined.
3263  *
3264  * @memberOf LABKEY.Query
3265  * @function
3266  * @static
3267  * @name importData
3268  * @param {Object} config An object which contains the following configuration properties.
3269  * @param {String} config.schemaName Name of a schema defined within the current container.
3270  * @param {String} config.queryName Name of a query table associated with the chosen schema.
3271  * @param {File} [config.file] A <a href='https://developer.mozilla.org/en-US/docs/DOM/File'><code>File</code></a> object or a file input element to upload to the server.
3272  * @param {String} [config.text] Text to import.
3273  * @param {String} [config.path] Path to resource under webdav tree. E.g. "/_webdav/MyProject/@files/data.tsv"
3274  * @param {String} [config.module] Module name to use when resolving a module resource.
3275  * @param {String} [config.moduleResource] A file resource within the module to import.
3276  * @param {String} [config.importIdentity] When true, auto-increment key columns may be imported from the data.
3277  * @param {String} [config.importLookupByAlternateKey] When true, lookup columns can be imported by their alternate keys instead of the primary key.
3278  *          For example, if a column is a lookup to a SampleSet, the imported value can be the Sample's name since names must be unique within a SampleSet.
3279  * @param {Function} [config.success] Function called when the "importData" function executes successfully.
3280  Will be called with the following arguments:
3281  An object containing success and rowCount properties.
3282  * @param {Function} [config.failure]  Function called importing data fails.
3283  * @param {String} [config.containerPath] The container path in which the schema and query name are defined.
3284  * @param {Integer} [config.timeout] The maximum number of milliseconds to allow for this operation before
3285  *       generating a timeout error (defaults to 30000).
3286  * @param {Object} [config.scope] A scope for the callback functions. Defaults to "this"
3287  * @returns {Mixed} In client-side scripts, this method will return a transaction id
3288  * for the async request that can be used to cancel the request
3289  * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection&member=abort" target="_blank">Ext.data.Connection.abort</a>).
3290  * In server-side scripts, this method will return the JSON response object (first parameter of the success or failure callbacks.)
3291  * @example Example, importing tsv data from a module: <pre name="code" class="javascript">
3292  LABKEY.Query.importData({
3293              schemaName: 'lists',
3294              queryName: 'People',
3295              // reference to <input type='file' id='file'>
3296              file: document.getElementById('file')
3297          },
3298  });</pre>
3299  * @example Example, importing tsv data from a module: <pre name="code" class="javascript">
3300  LABKEY.Query.importData({
3301              schemaName: 'lists',
3302              queryName: 'People',
3303              module: 'mymodule',
3304              moduleResource: '/data/lists/People.tsv'
3305          },
3306  });</pre>
3307  */
3308