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