/** Query is returned from Session.createQuery().
 *
 * Query is created based on a mapped domain object, a mapped constructor,
 * or a table name. It contains properties, one for each persistent property
 * in the domain object. If created based on a table name, the properties
 * correspond exactly to columns in the table. These properties
 * can be used to construct filters (where clauses for the query).
 * Query also contains a reference to the Session that created it.
 * Query can be executed, passing a parameters object that governs how the
 * query will be executed.
 * 
 */

/** Specify the filter for this query. Where returns the Query to allow
 * function chaining.
 */
  where(queryPredicate);

/** execute()
 * ASYNC
 * Execute this query using the parameters specified. 
 * Parameters is an object with one property holding a value for each 
 * parameter specified by the query param function, and optional keywords 
 * that govern how the query is executed.
 * Keywords are:
 *    'order' value: 'asc' or 'desc'; default: no order
 *    'skip' value: number of rows to skip from the result; default: 0
 *    'limit' value: number of rows to return; default: a couple of billion
 *
 * execute() returns a promise.  On success, the promise will be fulfilled 
 * with a value holding an array of query results.  The optional callback 
 * an error value and the query results.  Any extra arguments passed after 
 * the callback will be passed to the callback function verbatim as 
 * parameters following the results.
 *
 * The results of the query are returned in the callback.
 * The query is executed in the context of the session's current state:
 * autocommit if a transaction has not been started;
 * default lock mode;
 * the partition key.
 * @return promise
 */
 execute(queryParameters, [callback], [...]);

/** Count the number of instances filtered by this query.
 * XXX Not implemented in this version. XXX
 */
 count(Object parameters, 
       Function(error, numberOfInstancesFiltered, ... ) callback,
       ...);

/** Delete the instances filtered by this query.
 * XXX Not implemented in this version. XXX
 */
 delete(Object parameters, 
        Function(error, numberOfInstancesDeleted, ...) callback,
        ...);

/** Get the session from which this query was created.
 * @return the session
 * IMMEDIATE
 */
 getSession();

/** QueryParameter represents a named parameter used to pass values to a query.
 * QueryParameter is created directly from the Query, e.g. 
 * session.createQuery(t_basic, function(err, query) {
 *   var idParam = query.param('p_id');   // idParam is a QueryParameter
 *   var idField = query.id;              // idField is a QueryField
 *   var predicate = idField.eq(idParam); // predicate is a QueryPredicate
 *   query.where(predicate);
 *
 *   fluently, the above could be written as: 
 *            query.where(query.id.eq(query.param('p_id')));
 *
 *   query.execute({'p_id': 112}, function(err, results) {
 *   ...
 *   }
 * }
 * When executing a query, the value for each parameter is substituted by the 
 * value of the named property in the first argument to the execute function.
 */
 function QueryParameter();

/** QueryField represents a property in the domain object that is used
 * in a filter. Each persistent property in the domain object has a 
 * corresponding QueryField in the Query object.
 * The QueryField can be accessed directly from the Query, e.g. 
 * session.createQuery(t_basic, function(err, query) {
 *   var idField = query.id; // idField is a QueryField
 *   var predicate = idField.eq(query.param('p_id'); // predicate is a QueryPredicate
 *   ...
 * }
 * A QueryField can also be obtained from the Query property 'field'. This is 
 * useful to clarify the intent in cases where the column name is a reserved 
 * word in mysql-js Query.
 * For example, whereField1 and whereField2 represent the same query field.
 *   var whereField1 = query.where; // 'where' is the name of the column
 *   var whereField2 = query.field.where;
 * IMMEDIATE
 */
 function QueryField();

/** eq represents equal comparison of a property and a parameter.
 * @return QueryPredicate
 */
 function eq(Object parameterOrLiteral);

/** ne represents not equal comparison of a property and a parameter.
 * @return QueryPredicate
 * IMMEDIATE
 */
 function ne(Object parameterOrLiteral);

/** gt represents greater than comparison of a property and a parameter.
 * @return QueryPredicate
 * IMMEDIATE
 */
 function gt(Object parameterOrLiteral);

/** ge represents greater than or equal comparison of a property and parameter.
 * @return QueryPredicate
 * IMMEDIATE
 */
 function ge(Object parameterOrLiteral);

/** lt represents less than comparison of a property and a parameter.
 * @return QueryPredicate
 * IMMEDIATE
 */
 function lt(Object parameterOrLiteral);

/** le represents less than or equal comparison of a property and a parameter.
 * @return QueryPredicate
 * IMMEDIATE
 */
 function le(Object parameterOrLiteral);

/** between represents between comparison of a property and a lower bound 
 * and an upper bound parameter using greater equal and less equal semantics.
 * @return QueryPredicate
 * IMMEDIATE
 */
 function between(Object parameterOrLiteral, Object parameterOrLiteral);

/** QueryPredicate represents the result of comparing a query field to a
 * parameter. QueryPredicate can be used as the filter for a query or can be
 * combined with other QueryPredicates using boolean functions 'and', 'or', 
 * and unary function 'not'.
 */
 function QueryPredicate();

/** and represents the and condition joining this QueryPredicate with another.
 * @return QueryPredicate
 * IMMEDIATE
 */
 function and(QueryPredicate other);

/** or represents the or condition joining this QueryPredicate with another.
 * @return QueryPredicate
 * IMMEDIATE
 */
 function or(QueryPredicate other);

/** not represents the negation of this QueryPredicate.
 * @return QueryPredicate
 * IMMEDIATE
 */
 function not(QueryPredicate other);
