/*
   Copyright (c) 2013, 2020, Oracle and/or its affiliates.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License, version 2.0,
   as published by the Free Software Foundation.

   This program is also distributed with certain software (including
   but not limited to OpenSSL) that is licensed under separate terms,
   as designated in a particular file or component or in included license
   documentation.  The authors of MySQL hereby grant you an additional
   permission to link the program and your derivative works with the
   separately licensed software that they have included with MySQL.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License, version 2.0, for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
*/

/** 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);

/** isNull represents null comparison of a property.
 * @return QueryPredicate
 * IMMEDIATE
 */
 function isNull();

/** isNotNull represents not-null comparison of a property.
 * @return QueryPredicate
 * IMMEDIATE
 */
 function isNotNull();

/** 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 functions 'and', 'or', 
 * 'andNot', 'orNot', and 'not'.
 */
 function QueryPredicate();

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

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

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

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

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