P2JQuery.java

/*
** Module   : P2JQuery.java
** Abstract : Defines common API for all legacy query implementations
**
** Copyright (c) 2004-2025, Golden Code Development Corporation.
**
** -#- -I- --Date-- --JPRM-- -----------------------------------Description-----------------------------------
** 001 ECF 20060102   @23792 Created initial version. Defines API common
**                           to all query implementations.
** 002 ECF 20060501   @25916 Added isPreselect method. Indicates query's
**                           preselection behavior.
** 003 ECF 20060504   @25971 Set superinterface to WrappedResource. Added
**                           addAccumulator variants.
** 004 ECF 20061023   @30606 Added setErrorIfNull() method. Previously,
**                           this method existed in various implementors
**                           of this interface, but it is required from
**                           the UI (BrowseWidget, specifically), so it
**                           was moved to this interface.
** 005 ECF 20061102   @30958 Added support for reposition notification and
**                           auto-fetch features.
** 006 ECF 20061204   @31575 Added methods to support browse.
** 007 SIY 20070502   @33427 Added notifyRepositionListeners() method.
** 008 ECF 20070716   @34509 Added methods:
**                              isStandalone()
**                              setStandalone(boolean)
**                              cleanup()
** 009 ECF 20080509   @38242 Added open() method. Necessary for converted
**                           OPEN QUERY statements.
** 010 SVL 20080604   @38530 currentRow() renamed to currentRowImpl().
**                           Added new currentRow() function as Progress-
**                           compatible version.
** 011 ECF 20080729   @39320 Added rowid support. Refactored reposition*()
**                           methods.
** 012 ECF 20081106   @40323 Added _isOffEnd(). Returns a boolean instead
**                           of a logical, primarily for internal, runtime
**                           use.
** 013 CA  20081210   @40838 Implemented CLOSE QUERY statement.
** 014 ECF 20090312   @42984 Added getTableCount(). Moved up from Joinable
**                           interface to support NUM-BUFFERS attribute on a
**                           query handle.
** 015 CA  20090731   @43467 Added getOffEndListeners, which returns a list of
**                           all off-end listeners for all used buffers.
** 016 SVL 20091030   @44294 Added getOffEnd() function.
** 017 VMN 20130127          Added support for handle-based methods:
**                           GET-BUFFER-HANDLE (KW_GET_BUFH)
**                           GET-CURRENT (KW_GET_CUR),
**                           QUERY-CLOSE (KW_QRY_CLOS),
**                           REPOSITION-FORWARD (KW_REPOS_F),
**                           REPOSITION-TO-ROW (KW_REPOS_2R)
**                           REPOSITION-TO-ROWID (KW_REPOS_2I)
**                           and attributes
**                           NUM-RESULTS (KW_NUM_RES)
** 018 OM  20130114          Added declarations for SET-BUFFERS(KW_SET_BUF), 
**                           QUERY-PREPARE(KW_QRY_PREP), and QUERY-OPEN(KW_QRY_OPEN).
** 019 VMN 20130213          Added support for attributes
**                           INDEX-INFORMATION (KW_IDX_INFO)
**                           FORWARD-ONLY (KW_FWD_ONLY)
**                           PREPARE_STRING (KW_PREP_STR)
** 020 VMN 20130219          Added support for attributes
**                           IS-OPEN (KW_IS_OPEN)
** 021 CA  20130221          Added ADM-DATa, UNIQUE-ID and CommonHandleChain support.
** 022 VMN 20130306          Corrected support for handle-based methods:
**                           GET-NEXT (KW_GET_NEXT)
**                           GET-PREV (KW_GET_PREV)
**                           GET-FIRST (KW_GET_1ST)
**                           GET-LAST (KW_GET_LAST)
**                           GET-CURRENT (KW_GET_CUR)
**                           Added addBuffer(handle bufHandle)
** 023 CA  20130311          Added bufferHandle(integer).
** 024 VMN 20130311          Cosmetics (changed parameter names and comments)
** 025 VMN 20130312          Corrected conversion and runtime for
**                           REPOSITION-TO-ROW (KW_REPOS_2R)
** 026 CA  20130315          Added missing INDEX-INFORMATION API.
** 027 OM  20130320          Added missing DELETE-RESULT-LIST-ENTRY and CREATE-RESULT-LIST-ENTRY
**                           by extending ResultListHandler interface
** 028 VMN 20130321          Corrected conversion and runtime for
**                           NUM-BUFFERS attribute(KW_NUM_BUFF)
** 029 CA  20130322          Added missing queryForward(integer) API.
** 030 SVL 20130325          Added include and exclude functions.
** 031 CA  20130927          Added LegacyResource annotation, to determine resource type.
** 032 EVL 20131002          Adding legacy attributes and methods annotation.
** 033 CA  20131024          The legacy QUERY resource is implemented by the QueryWrapper class. 
**                           Query blocks (i.e. FOR EACH) do not have legacy query resource 
**                           behavior. Note that this interface is still used to define all the 
**                           QUERY-specific attributes/methods.
** 034 ECF 20131028          Import change.
** 035 SVL 20140909          Added isNativelyPreselect and deleteResultListEntry.
** 036 ECF 20141124          Added support for REPOSITION-BACKWARD.
** 037 SVL 20150331          Added deleteResultListEntry(boolean).
** 038 SVL 20150722          Updated notifyRepositionListeners signature.
** 039 ECF 20150715          Added optimize method.
** 040 SVL 20150821          Added isScrolling, removeRepositionListener, isBrowsed.
** 041 ECF 20150907          Added inner, functional interface Parameter.
** 042 OM  20150915          Added SKIP-DELETED-RECORD query attribute.
** 043 EVL 20160217          Clean up comments from symbols invalid for Solaris to compile.
** 044 SVL 20160314          Added setParameterFilter.
** 045 SVL 20160709          Make this class extend IndexInformation.
** 046 ECF 20160725          Added setExternalBuffers method and some methods needed by converted
**                           CAN-FIND functions.
** 047 CA  20161012          Fixed scope processing when the query is from a persistent 
**                           procedure, and is part of a QUERY resource.
** 048 SVL 20170126          Added bufferHandle(), changed signature of
**                           queryForward/queryBackward.
**     OM  20170209          Added return value for repositioning methods.
** 049 OM  20171129          Added releaseBuffers() method.
** 050 ECF 20180201          Removed optimize method. Cleaned up inheritance hierarchy.
** 051 OM  20180515          Added method declarations for dynamic filters and dynamic sort.
**     OM  20180924          Filtering on decimal fields uses STRING(f, format) function.
** 052 CA  20181108          Moved IS-OPEN to its own interface.
** 053 OM  20181206          Added partial support for QUERY-OPEN events.
**     CA  20181220          Added REPOSITION-TO-ROWID(character).
**                           SET-BUFFERS can receive a mix of char,handle and Buffer args.
**                           Added LAST-OF(int) and FIRST-OF(int) method stubs.
**                           Added ADD-BUFFER(character) stub.
** 054 ECF 20190302          Renamed setExternalBuffers to addExternalBuffers and changed
**                           implementation, since it may be called multiple times on a query.
** 055 SVL 20190320          Added createResultListEntry.
** 056 OM  20190409          Extracted common interface with DataSet in BufferCollection.
**     CA  20190416          Added QUERY:BASIC-LOGGING.
** 057 OM  20190720          Added repositionByID() for internal usage.
**     EVL 20190827          Added one more interface QueryOpenedListener to handle the cases when
**                           we need some actions to perform after query has been opened.
** 058 CA  20191005          A query must know if it is dynamic, when closing.
** 059 CA  20200503          Added QUERY:CACHE runtime stub.
** 060 ECF 20200906          New ORM implementation.
** 061 CA  20200918          INDEX-INFORMATION requires to interpret the 'execute' method for a dynamic query
**                           without evaluating the dynamic calls in the WHERE.
**     CA  20210310          A dynamic predicate must set the default lock to NONE, instead of SHARE.
**     ECF 20210723          Changed signature of query close worker method.
**     ECF 20210815          Added isFindByRowid method.
**     AL2 20210909          Added support for indexed reposition.
**     ECF 20210911          Javadoc fix.
**     CA  20210920          When a buffer is deleted, all related queries must be reset (their predicate and
**                           buffer list).
**     OM  20220112          Added default implementation for new property 'fillingBrowseRows'.
** 062 IAS 20230105          Fixed FILL support for recursive DATA-RELATION
** 063 AL2 20230411          Added query close listeners.
** 064 IAS 20230717          Added 'ParamResolver' interface definition.
** 065 ES  20231203          Changed first, last, next, previous, current, unique methods to return boolean,
**                           instead of void. These methods now returns true if operation was succesful, and false 
**                           not and lenientOffEnd is set on true, otherwise it throwd an QQE exception.
**     ES  20231203          Added new setLenientOffEnd method.
** 066 AL2 20240307          Mark the query to retrieve the entire result set (useful for FILL operations).
** 067 CA  20240320          Avoid BDTs within internal FWD runtime.  Replaced iterators with Java 'for',
**                           where it applies.
** 068 ES  20240404          Added new setIteration, isIteration, setPresort and isPresort methods.
** 069 CA  20240422          Allow the query to be reset to its initialization state, so the same instance can
**                           be used to execute child buffer FILL operations.
** 070 CA  20240809          Avoid iterator usage, for performance improvement.
** 071 SP  20240917          ParamResolver should always return a character type.
** 072 DDF 20230712          Added setForwardOnly() method.
**     DDF 20230713          Added isForwardOnly() method.
** 073 OM  20241128          Multi-tenant runtime support: selected the proper persistence context, eventually
**                           based on [sharedDb] parameter.
**                           Implementation of [setMultiTenantAlternative] method.
** 074 ICP 20250129          Used logical constant to leverage cached instances.
** 075 AL2 20250416          Added support for force-database-join attribute.
** 076 CA  20250422          Added support for REPOSITION-BY-ID(rowid[]), where the arg is an extent.
*/

/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** 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 Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
** 
** Additional terms under GNU Affero GPL version 3 section 7:
** 
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
**   terms apply to the works covered under the License.  These additional terms
**   are non-permissive additional terms allowed under Section 7 of the GNU
**   Affero GPL version 3 and may not be removed by you.
** 
**   0. Attribution Requirement.
** 
**     You must preserve all legal notices or author attributions in the covered
**     work or Appropriate Legal Notices displayed by works containing the covered
**     work.  You may not remove from the covered work any author or developer
**     credit already included within the covered work.
** 
**   1. No License To Use Trademarks.
** 
**     This license does not grant any license or rights to use the trademarks
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
**     of Golden Code Development Corporation. You are not authorized to use the
**     name Golden Code, FWD, or the names of any author or contributor, for
**     publicity purposes without written authorization.
** 
**   2. No Misrepresentation of Affiliation.
** 
**     You may not represent yourself as Golden Code Development Corporation or FWD.
** 
**     You may not represent yourself for publicity purposes as associated with
**     Golden Code Development Corporation, FWD, or any author or contributor to
**     the covered work, without written authorization.
** 
**   3. No Misrepresentation of Source or Origin.
** 
**     You may not represent the covered work as solely your work.  All modified
**     versions of the covered work must be marked in a reasonable way to make it
**     clear that the modified work is not originating from Golden Code Development
**     Corporation or FWD.  All modified versions must contain the notices of
**     attribution required in this license.
*/

package com.goldencode.p2j.persist;

import java.util.ArrayList;
import java.util.function.*;
import com.goldencode.p2j.persist.event.*;
import com.goldencode.p2j.persist.lock.*;
import com.goldencode.p2j.util.*;

/**
 * The minimal API all query implementations must provide.  Defines methods
 * to retrieve and navigate results and to access query metadata.
 */ 
public interface P2JQuery
extends BufferCollection,
        IndexInformation,
        Openable
{
   /**
    * Clear the current results from the query, so the same query instance can be executed again, without 
    * having to {@link #open() re-open} it.
    */
   public void clearResults();
   
   /**
    * Set this query in a 'dynamic' mode, to mark the fact that it is originating from a dynamic predicate.
    * 
    * @param    dynamic
    *           Flag indicating that this is from a dynamic predicate for a query resource.
    */
   public default void setDynamicPredicate(boolean dynamic)
   {
      // no-op
   }
   
   /**
    * Check if this query is originating from a dynamic predicate.
    * 
    * @return   Always <code>false</code>.
    */
   public default boolean isDynamicPredicate()
   {
      return false;
   }
   
   /**
    * Enable results list scrolling/repositioning.
    */
   public void setScrolling();
   
   /**
    * Indicate whether this query was defined as SCROLLING.
    *
    * @return  <code>true</code> if this query is scrolling.
    */
   public boolean isScrolling();
   
   /**
    * Enables/disables forward-only.
    * When forward-only is enabled (set to <code>true</code>), GET PREV, GET LAST, REPOSITION
    * and BROWSE can't be used, or an error will be thrown.
    * 
    * @param   value
    *          <code>true</code> to enable forward-only, <code>false</code> to disable it.
    */
   public void setForwardOnly(boolean value);
   
   /**
    * Method that returns the value of the forwardOnly flag.
    * 
    * @return  <code>true</code> if forward-only is enabled, <code>false</code> otherwise.
    */
   public boolean isForwardOnly();
   
   /**
    * Enforce a database join if possible. By default, multi-table queries rely on 
    * algorithm to decide whether a database join is optimal or not. With such setter,
    * the database join is always preferred.
    * 
    * @param   forceDatabaseJoin
    *          {@code true} if the query should always use DB joins.
    */
   public void setForceDatabaseJoin(logical forceDatabaseJoin);
   
   /**
    * Check if the database join enforcing is active.
    * 
    * @return   {@code true} if the query will always use DB joins.
    */
   public logical isForceDatabaseJoin();
   
   /**
    * Enable indexed reposition optimization.
    */
   public void setIndexedReposition();
   
   /**
    * Indicate whether this query was optimized using indexed reposition.
    *
    * @return  <code>true</code> if this query is indexed reposition.
    */
   public boolean isIndexedReposition();
   
   /**
    * Open the prepared query.
    */
   public void open();
   
   /**
    * Explicitly close the prepared query.
    */
   public void close();
   
   /**
    * Explicitly close the prepared query.
    * 
    * @param    inResource
    *           Flag indicating this query is used in a QUERY legacy resource.
    */
   public default void close(boolean inResource)
   {
      // no-op by default
   }
   
   /**
    * Reset the query (this does not close the query).
    */
   public default void resetQuery()
   {
      // no-op by default
   }
   
   /**
    * Get the number of tables joined by this query.
    *
    * @return  Number of joined tables.
    */
   public int getTableCount();
   
   /**
    * Get an array of all record buffers managed by this query.
    *
    * @return  All record buffers managed by this query.
    */
   public default RecordBuffer[] getRecordBuffers()
   {
      // return null by default, as this is meant to be an internal API; implementing classes
      // should override this default as needed
      return null;
   }
   
   /**
    * Add one or more buffers to the list of those which this query references externally. These
    * typically will be buffers referenced by converted CAN-FIND expressions embedded in the
    * query's HQL expression, which are not the primary buffers associated with the query.
    * 
    * @param   dmos
    *          One or more external buffers.
    * 
    * @return  This instance, so that this method can be chained to the constructor and return
    *          this instance to the caller.
    */
   public P2JQuery addExternalBuffers(DataModelObject... dmos);
   
   /**
    * Adds an alternative execution query, for the multi-tenant case in which the CAN-FIND nested buffer and
    * the main buffer of query component do not belong to same physical database.
    * <p>
    * This method will be generated only in case of multi-tenant projects, in the condition above-mentioned.
    *
    * @param   where
    *          FQL where clause.  May be {@code null}.
    * @param   whereExpr
    *          Client-side where clause expression. May be {@code null} but this is probably caused by an
    *          incorrect conversion.
    * @param   sort
    *          The sort order.
    *
    * @return  Self object so that the call to this method can be optionally chained with the constructor.
    */
   public P2JQuery setMultiTenantAlternative(String where, Supplier<logical> whereExpr, String sort);
   
   /**
    * Adds an alternative execution query, for the multi-tenant case in which the CAN-FIND nested buffer and
    * the main buffer of query component do not belong to same physical database.
    * <p>
    * This method will be generated only in case of multi-tenant projects, in the condition above-mentioned.
    *
    * @param   where
    *          FQL where clause.  May be {@code null}.
    * @param   whereExpr
    *          Client-side where clause expression. May be {@code null} but this is probably caused by an
    *          incorrect conversion.
    * @param   sort
    *          The sort order.
    * @param   args
    *          Substitution parameters for FQL queries. These will be used if not overridden by a record
    *          retrieval method.
    *
    * @return  Self object so that the call to this method can be optionally chained with the constructor.
    */
   public P2JQuery setMultiTenantAlternative(String where,
                                             Supplier<logical> whereExpr,
                                             String sort,
                                             Object[] args);
   
   /**
    * Get the legacy natural join, if any, associated with this query.
    * 
    * @return  Legacy join object, or <code>null</code> if none.
    */
   public default AbstractJoin getJoin()
   {
      // return null by default, as this is meant to be an internal API, and not all query types
      // support this operation
      return null;
   }
   
   /**
    * Get all the off-end listeners associated with this query.
    * 
    * @return  the off-end listeners associated with this query.
    */
   public ArrayList<QueryOffEndListener> getOffEndListeners();
   
   /**
    * Set a mode such that setting a null record into a backing buffer may or
    * may not result in an error condition.  This applies only to requests to
    * retrieve <code>FIRST</code>, <code>LAST</code>, and <code>UNIQUE</code>
    * records.
    *
    * @param   errorIfNull
    *          If <code>true</code>, setting a <code>null</code> value as the
    *          current record in an underlying buffer will raise an error
    *          condition (if not in silent error mode); if <code>false</code>,
    *          this action will raise an end condition instead.
    */
   public void setErrorIfNull(boolean errorIfNull);
   
   /**
    * Set the behavior of this query as a record retrieval request moves off
    * the end of its results.  If set to lenient mode, invocations of
    * <code>next</code> and <code>previous</code> which do not find a record
    * do not raise a <code>QueryOffEndException</code>.  By default, this
    * would normally raise the exception.
    *
    * @param   lenientOffEnd
    *          <code>true</code> to suppress <code>QueryOffEndException</code>
    *          for <code>next</code> and <code>previous</code> requests;
    *          <code>false</code> to permit these exceptions.
    */
   public void setLenientOffEnd(boolean lenientOffEnd);
   
   /**
    * Indicate whether the query is defined inside the scope of FOR EACH block.
    *
    * @param   iterating
    *          <code>true</code> indicating that a query is inside FOR EACH block;
    *          <code>false</code> is defined outside of a FOR EACH.
    */
   public void setIterating(boolean iterating);
    
   /**
   * Indicate whether the query is defined inside the scope of FOR EACH block.
   *
   * @return  <code>true</code> if the query was defined inside a FOR EACH block.
   */
   public boolean isIterating();
   
   /**
    * Indicate whether the query is of presort type.
    *
    * @return  <code>true</code> if the query is of presort type..
    */
   public boolean isPresort();
   
   /**
    * Indicate whether the query is of presort type.
    *
    * @param   presort
    *          <code>true</code> indicating that a query of presort type.
    *          <code>false</code> is not of presort type.
    */
   public void setPresort(boolean presort);
   
   /**
    * Add an accumulator to this query.  The accumulator expects to be
    * notified whenever a new result row is accessed (during sequential row
    * access).
    * <p>
    * This implementation assumes the accumulator is not associated with a
    * break group.
    *
    * @param   accum
    *          Accumulator to be registered with this query.
    */
   public void addAccumulator(Accumulator accum);
   
   /**
    * Add an accumulator to this query.  The accumulator expects to be
    * notified whenever a new result row is accessed (during sequential row
    * access).
    * <p>
    * This implementation assumes the accumulator is not associated with a
    * break group.
    *
    * @param   accum
    *          Accumulator to be registered with this query.
    * @param   deferred
    *          <code>true</code> to defer accumulator recalculation until the
    *          next invocation of {@link
    *          com.goldencode.p2j.util.Accumulator#accumulate()}.  If
    *          <code>false</code>, the accumulator recalculates its internal
    *          state as soon as the query's next result is fetched.
    */
   public void addAccumulator(Accumulator accum, boolean deferred);
   
   /**
    * Retrieve the first composite row of results for the query.  The
    * underlying buffer for each query component is updated with the
    * appropriate record.
    * <p>
    * If the query involves outer joins, some of the underlying buffers may
    * be empty when this method returns.
    * 
    * @return  <code>true</code> if query could retrive the first record succefully;
    *          <code>false</code> if unsuccessful and <code>lenientOffEnd</code> is set on true.
    * 
    * @throws  ErrorConditionException
    *          if the query or the fetch of any record fails, or if no records
    *          are available and the query is set to fail in this case.
    * @throws  QueryOffEndException
    *          if no records are available and the query is set not to fail
    *          in this case.
    */
   public boolean first();
   
   /**
    * Retrieve the first composite row of results for the query.  The
    * underlying buffer for each query component is updated with the
    * appropriate record.
    * <p>
    * If the query involves outer joins, some of the underlying buffers may
    * be empty when this method returns.
    *
    * @param   lockType
    *          Lock type to apply to records retrieved (overrides default
    *          lock type set for each query component).
    * 
    * @return  <code>true</code> if query could retrive the first record succefully;
    *          <code>false</code> if unsuccessful and <code>lenientOffEnd</code> is set on true.
    * 
    * @throws  ErrorConditionException
    *          if the query or the fetch of any record fails, or if no records
    *          are available and the query is set to fail in this case.
    * @throws  QueryOffEndException
    *          if no records are available and the query is set not to fail
    *          in this case.
    */
   public boolean first(LockType lockType);
   
   /**
    * Retrieve the last composite row of results for the query.  The
    * underlying buffer for each query component is updated with the
    * appropriate record.
    * <p>
    * If the query involves outer joins, some of the underlying buffers may
    * be empty when this method returns.
    * 
    * @return  <code>true</code> if query could retrive the last record succefully;
    *          <code>false</code> if unsuccessful and <code>lenientOffEnd</code> is set on true.
    * 
    * @throws  ErrorConditionException
    *          if the query or the fetch of any record fails, or if no records
    *          are available and the query is set to fail in this case.
    * @throws  QueryOffEndException
    *          if no records are available and the query is set not to fail
    *          in this case.
    */
   public boolean last();
   
   /**
    * Retrieve the last composite row of results for the query.  The
    * underlying buffer for each query component is updated with the
    * appropriate record.
    * <p>
    * If the query involves outer joins, some of the underlying buffers may
    * be empty when this method returns.
    *
    * @param   lockType
    *          Lock type to apply to records retrieved (overrides default
    *          lock type set for each query component).
    * 
    * @return  <code>true</code> if query could retrive the last record succefully;
    *          <code>false</code> if unsuccessful and <code>lenientOffEnd</code> is set on true.
    *
    * @throws  ErrorConditionException
    *          if the query or the fetch of any record fails, or if no records
    *          are available and the query is set to fail in this case.
    * @throws  QueryOffEndException
    *          if no records are available and the query is set not to fail
    *          in this case.
    */
   public boolean last(LockType lockType);
   
   /**
    * Retrieve the next composite row of results for the query.  The
    * underlying buffer for each query component is updated with the
    * appropriate record.
    * <p>
    * If the query involves outer joins, some of the underlying buffers may
    * be empty when this method returns.
    *
    * @return  <code>true</code> if query could retrive the next record succefully;
    *          <code>false</code> if unsuccessful and <code>lenientOffEnd</code> is set on true.
    *
    * @throws  ErrorConditionException
    *          if the query or the fetch of any record fails, or if no records
    *          are available and the query is set to fail in this case.
    * @throws  QueryOffEndException
    *          if no records are available and the query is set not to fail
    *          in this case.
    */
   public boolean next();
   
   /**
    * Retrieve the next composite row of results for the query.  The
    * underlying buffer for each query component is updated with the
    * appropriate record.
    * <p>
    * If the query involves outer joins, some of the underlying buffers may
    * be empty when this method returns.
    *
    * @param   lockType
    *          Lock type to apply to records retrieved (overrides default
    *          lock type set for each query component).
    * 
    * @return  <code>true</code> if query could retrive the next record succefully;
    *          <code>false</code> if unsuccessful and <code>lenientOffEnd</code> is set on true.
    * 
    * @throws  ErrorConditionException
    *          if the query or the fetch of any record fails, or if no records
    *          are available and the query is set to fail in this case.
    * @throws  QueryOffEndException
    *          if no records are available and the query is set not to fail
    *          in this case.
    */
   public boolean next(LockType lockType);
   
   /**
    * Retrieve the previous composite row of results for the query.  The
    * underlying buffer for each query component is updated with the
    * appropriate record.
    * <p>
    * If the query involves outer joins, some of the underlying buffers may
    * be empty when this method returns.
    * 
    * @return  <code>true</code> if query could retrive the previous record succefully;
    *          <code>false</code> if unsuccessful and <code>lenientOffEnd</code> is set on true.
    * 
    * @throws  ErrorConditionException
    *          if the query or the fetch of any record fails, or if no records
    *          are available and the query is set to fail in this case.
    * @throws  QueryOffEndException
    *          if no records are available and the query is set not to fail
    *          in this case.
    */
   public boolean previous();
   
   /**
    * Retrieve the previous composite row of results for the query.  The
    * underlying buffer for each query component is updated with the
    * appropriate record.
    * <p>
    * If the query involves outer joins, some of the underlying buffers may
    * be empty when this method returns.
    * 
    * @param   lockType
    *          Lock type to apply to records retrieved (overrides default
    *          lock type set for each query component).
    *
    * @return  <code>true</code> if query could retrive the previous record succefully;
    *          <code>false</code> if unsuccessful and <code>lenientOffEnd</code> is set on true.
    *
    * @throws  ErrorConditionException
    *          if the query or the fetch of any record fails, or if no records
    *          are available and the query is set to fail in this case.
    * @throws  QueryOffEndException
    *          if no records are available and the query is set not to fail
    *          in this case.
    */
   public boolean previous(LockType lockType);
   
   /**
    * Retrieve a unique record (only valid for a single-table query).
    * 
    * @return  <code>true</code> if query could retrive the unique record succefully;
    *          <code>false</code> if unsuccessful and <code>lenientOffEnd</code> is set on true.
    * 
    * @throws  ErrorConditionException
    *          if the query fails or if more than one result is found which
    *          matches the query criteria.
    */
   public default boolean unique()
   {
      return false;
      // no-op by default, as this is not meaningful for all query types
   }
   
   /**
    * Retrieve a unique record (only valid for a single-table query),
    * overriding the default lock type of the underlying query component.
    *
    * @param   lockType
    *          Lock type which should override that of the query component.
    * 
    * @return  <code>true</code> if query could retrive the unique record succefully;
    *          <code>false</code> if unsuccessful and <code>lenientOffEnd</code> is set on true.
    * 
    * @throws  ErrorConditionException
    *          if the query fails or if more than one result is found which
    *          matches the query criteria.
    */
   public default boolean unique(LockType lockType)
   {
      return false;
      // no-op by default, as this is not meaningful for all query types
   }
   
   /**
    * Reload the current composite row of results for the query.
    * <p>
    * If the query involves outer joins, some of the underlying buffers may
    * be empty when this method returns.
    * 
    * @return  <code>true</code> if query could retrive the current record succefully;
    *          <code>false</code> if unsuccessful and <code>lenientOffEnd</code> is set on true.
    * 
    * @throws  ErrorConditionException
    *          if the reload triggers an error.
    */
   public boolean current();
   
   /**
    * Reload the current composite row of results for the query, overriding
    * the lock type to apply to each record.
    * <p>
    * If the query involves outer joins, some of the underlying buffers may
    * be empty when this method returns.
    *
    * @param   lockType
    *          Lock type which should override that of any query component.
    * 
    * @return  <code>true</code> if query could retrive the current record succefully;
    *          <code>false</code> if unsuccessful and <code>lenientOffEnd</code> is set on true.
    * 
    * @throws  ErrorConditionException
    *          if the reload triggers an error.
    */
   public boolean current(LockType lockType);
   
   /**
    * Indicate whether a request to find the first result of this query would
    * succeed or fail.
    * <p>
    * Default substitution arguments and a lock type of <code>NONE</code> are
    * used for this test.
    *
    * @return  <code>true</code> if the first record exists, else
    *          <code>false</code>.
    */
   public logical hasAny();
   
   /**
    * Indicate whether a request to find the first result of this query would
    * succeed or fail.
    * <p>
    * The specified substitution arguments and a lock type of
    * <code>NONE</code> are used for this test.
    * 
    * @param   values
    *          Query substitution parameters.
    *
    * @return  <code>true</code> if the first record exists, else
    *          <code>false</code>.
    */
   public logical hasAny(Object[] values);
   
   /**
    * Indicate whether a request to find the first result of this query would
    * succeed or fail.
    * <p>
    * Default substitution arguments and the specified lock type are used for
    * this test.
    *
    * @param   lockType
    *          Lock type for the query.  This lock is not actually acquired,
    *          only tested for availability.
    *
    * @return  <code>true</code> if the first record exists, else
    *          <code>false</code>.
    */
   public logical hasAny(LockType lockType);
   
   /**
    * Indicate whether a request to find the first result of this query would
    * succeed or fail.
    * <p>
    * The specified substitution arguments and lock type are used for this
    * test.
    *
    * @param   values
    *          Query substitution parameters.
    * @param   lockType
    *          Lock type for the query.  This lock is not actually acquired,
    *          only tested for availability.
    *
    * @return  <code>true</code> if the first record exists, else
    *          <code>false</code>.
    */
   public logical hasAny(Object[] values, LockType lockType);
   
   /**
    * Indicate whether this query would produce a unique result.
    * <p>
    * Default substitution arguments and a lock type of <code>NONE</code> are
    * used for this test.
    *
    * @return  <code>true</code> if any record matching the query's criteria
    *          exists, else <code>false</code>.
    */
   public logical hasOne();
   
   /**
    * Indicate whether this query would produce a unique result.
    * <p>
    * The specified substitution arguments and a lock type of
    * <code>NONE</code> are used for this test.
    *
    * @param   values
    *          Query substitution parameters.
    *
    * @return  <code>true</code> if any record matching the query's criteria
    *          exists, else <code>false</code>.
    */
   public logical hasOne(Object[] values);
   
   /**
    * Indicate whether this query would produce a unique result.
    * <p>
    * Default substitution arguments and the specified lock type are used for
    * this test.
    *
    * @param   lockType
    *          Lock type for the query.  This lock is not actually acquired,
    *          only tested for availability.
    *
    * @return  <code>true</code> if any record matching the query's criteria
    *          exists, else <code>false</code>.
    */
   public logical hasOne(LockType lockType);
   
   /**
    * Indicate whether this query would produce a unique result.
    * <p>
    * The specified substitution arguments and lock type are used for this
    * test.
    *
    * @param   values
    *          Query substitution parameters.
    * @param   lockType
    *          Lock type for the query.  This lock is not actually acquired,
    *          only tested for availability.
    *
    * @return  <code>true</code> if any record matching the query's criteria
    *          exists, else <code>false</code>.
    */
   public logical hasOne(Object[] values, LockType lockType);
   
   /**
    * Determine whether the query result row currently being visited is the first row of the
    * query's result set or the first row within a break group whose category is identified by
    * the specified BREAK-BY level.
    *
    * @param   level
    *          Break group level, where 0 is the whole query, 1 is the first BREAK-BY sort
    *          criterion, etc. Must not be negative or greater than the number of sort criteria.
    *          Must not be unknown value.
    *
    * @return  {@code true} if the current row is first in the result set or within the specified
    *          break group; else {@code false}.
    */
   @LegacyMethod(name = "FIRST-OF")
   public default logical isFirstOfGroup(integer level)
   {
      UnimplementedFeature.todo("FIRST-OF");
      return new logical();
   }
   
   /**
    * Determine whether the query result row currently being visited is the first row of the
    * query's result set or the first row within a break group whose category is identified by
    * the specified BREAK-BY level.
    *
    * @param   level
    *          Break group level, where 0 is the whole query, 1 is the first BREAK-BY sort
    *          criterion, etc. Must not be negative or greater than the number of sort criteria.
    *
    * @return  {@code true} if the current row is first in the result set or within the specified
    *          break group; else {@code false}.
    */
   @LegacyMethod(name = "FIRST-OF")
   public default logical isFirstOfGroup(int level)
   {
      UnimplementedFeature.todo("FIRST-OF");
      return new logical();
   }
   
   /**
    * Determine whether the query result row currently being visited is the last row of the
    * query's result set or the last row within a break group whose category is identified by
    * the specified BREAK-BY level.
    *
    * @param   level
    *          Break group level, where 0 is the whole query, 1 is the first BREAK-BY sort
    *          criterion, etc. Must not be negative or greater than the number of sort criteria.
    *          Must not be unknown value.
    *
    * @return  {@code true} if the current row is last in the result set or within the specified
    *          break group; else {@code false}.
    */
   @LegacyMethod(name = "LAST-OF")
   public default logical isLastOfGroup(integer level)
   {
      UnimplementedFeature.todo("LAST-OF");
      return new logical();
   }
   
   /**
    * Determine whether the query result row currently being visited is the last row of the
    * query's result set or the last row within a break group whose category is identified by
    * the specified BREAK-BY level.
    *
    * @param   level
    *          Break group level, where 0 is the whole query, 1 is the first BREAK-BY sort
    *          criterion, etc. Must not be negative or greater than the number of sort criteria.
    *
    * @return  {@code true} if the current row is last in the result set or within the specified
    *          break group; else {@code false}.
    */
   @LegacyMethod(name = "LAST-OF")
   public default logical isLastOfGroup(int level)
   {
      UnimplementedFeature.todo("LAST-OF");
      return new logical();
   }
   
   /**
    * Reposition the cursor such that a request to retrieve the next result
    * will retrieve the result which matches the specified primary key ID.  A
    * request to retrieve the previous result will retrieve the result
    * immediately previous to this, if any, in the results list.
    *
    * @param   id
    *          A primary key ID, representing the target record (in the case
    *          of a join, this ID is associated with the left-most record in
    *          the join).
    * 
    * @throws  ErrorConditionException
    *          if the specified ID represents the unknown value.
    */
   public void repositionByID(recid id);
   
   /**
    * Reposition the cursor such that a request to retrieve the next result
    * will retrieve the result which matches the specified array of primary
    * key IDs.  A request to retrieve the previous result will retrieve the
    * result immediately previous to this, if any, in the results list.
    *
    * @param   id1
    *          A primary key ID, representing the target record (in the case
    *          of a join, this ID is associated with the left-most record in
    *          the join).
    * @param   joinIDs
    *          All remaining primary key IDs, if any, arranged from left to
    *          right to coincide with the records being joined by the
    *          underlying query.
    * 
    * @throws  ErrorConditionException
    *          if any of the specified IDs represents the unknown value.
    */
   public void repositionByID(rowid id1, rowid...joinIDs);
   
   /**
    * Reposition the cursor such that a request to retrieve the next result will retrieve the
    * result which matches the specified array of primary key IDs. A request to retrieve the
    * previous result will retrieve the result immediately previous to this, if any, in the
    * results list.
    * <strong>Note:</strong> This is not public API.
    *
    * @param   joinIDs
    *          A set of primary key IDs, arranged from left to right to coincide with the records
    *          being joined by the underlying query.
    * 
    * @throws  ErrorConditionException
    *          if any of the specified IDs represents the unknown value.
    *
    * @return  {@code true} on success.
    */
   public boolean repositionByID(Long... joinIDs);
   
   /**
    * Reposition the cursor to the specified row in the result set.  The row
    * indicates the position between two results, such that a call to
    * retrieve the next record will get the result at the specified row,
    * and a call to retrieve the previous result will get the result before
    * the new position.
    *
    * @param   row
    *          1-based index of the target position.
    *
    * @throws  ErrorConditionException
    *          if <code>row</code> represents unknown value.
    */
   public void reposition(NumberType row);
   
   /**
    * Reposition the query to the specified row in the result set.  The row
    * indicates the position between two results, such that a call to
    * retrieve the next record will get the record after the new position,
    * and a call to retrieve the previous record will get the record before
    * the new position.
    *
    * @param   row
    *          1-based index of the target position.
    */
   public void reposition(int row);
   
   /**
    * Advance the current cursor position forward by the specified number of
    * rows.  This will always leave the cursor between two results.  For
    * example, given a request to move 1 row forward:
    * <ul>
    *   <li>if the cursor currently is positioned <i>directly on a result</i>,
    *       this would move it ahead <i>one and a half positions</i>, to just
    *       beyond the following result;
    *   <li>if the cursor currently is positioned <i>between two results</i>,
    *       this would move it ahead <i>one position</i>, to just beyond the
    *       following result.
    * </ul>
    *
    * @param   rows
    *          Number of rows to scroll the cursor forward.
    *
    * @return  {@code true} if operation was successful and the cursor was moved the exact amount
    *          of rows as specified by the parameter. If {@code false} is returned then it is
    *          possible that cursor's position was moved but not with {@code rows} rows.
    *
    * @throws  ErrorConditionException
    *          if <code>rows</code> represents the unknown value.
    */
   public boolean forward(NumberType rows);
   
   /**
    * Advance the current cursor position forward by the specified number of
    * rows.  This will always leave the cursor between two results.  For
    * example, given a request to move 1 row forward:
    * <ul>
    *   <li>if the cursor currently is positioned <i>directly on a result</i>,
    *       this would move it ahead <i>one and a half positions</i>, to just
    *       beyond the following result;
    *   <li>if the cursor currently is positioned <i>between two results</i>,
    *       this would move it ahead <i>one position</i>, to just beyond the
    *       following result.
    * </ul>
    *
    * @param   rows
    *          Number of rows to scroll the cursor forward.
    * @return  {@code true} if operation was successful and the cursor was moved the exact amount
    *          of rows as specified by the parameter. If {@code false} is returned then it is
    *          possible that cursor's position was moved but not with {@code rows} rows.
    */
   public boolean forward(int rows);
   
   /**
    * Move the current cursor position backward by the specified number of
    * rows.  This will always leave the cursor between two results.  For
    * example, given a request to move 1 row backward:
    * <ul>
    *   <li>if the cursor currently is positioned <i>directly on a result</i>,
    *       this would move it back <i>one half position</i>, to just
    *       before the current result;
    *   <li>if the cursor currently is positioned <i>between two results</i>,
    *       this would move it back <i>one position</i>, to just before the
    *       current result.
    * </ul>
    *
    * @param   rows
    *          Number of rows to scroll the cursor backward.
    *
    * @return  {@code true} if operation was successful and the cursor was moved the exact amount
    *          of rows as specified by the parameter. If {@code false} is returned then it is
    *          possible that cursor's position was moved but not with {@code rows} rows.
    *
    * @throws  ErrorConditionException
    *          if <code>rows</code> represents the unknown value.
    */
   public boolean backward(NumberType rows);
   
   /**
    * Move the current cursor position backward by the specified number of
    * rows.  This will always leave the cursor between two results.  For
    * example, given a request to move 1 row backward:
    * <ul>
    *   <li>if the cursor currently is positioned <i>directly on a result</i>,
    *       this would move it back <i>one half position</i>, to just
    *       before the current result;
    *   <li>if the cursor currently is positioned <i>between two results</i>,
    *       this would move it back <i>one position</i>, to just before the
    *       current result.
    * </ul>
    *
    * @param   rows
    *          Number of rows to scroll the cursor backward.
    *
    * @return  {@code true} if operation was successful and the cursor was moved the exact amount
    *          of rows as specified by the parameter. If {@code false} is returned then it is
    *          possible that cursor's position was moved but not with {@code rows} rows.
    */
   public boolean backward(int rows);
   
   /**
    * Get the <b><i>current</i></b> size of the cached results list.  However,
    * since this cache may be built progressively as the query is scrolled,
    * repositioned, and naturally navigated, this <b>does not</b> necessarily
    * represent the full count of results which may satisfy the query.
    *
    * @return  Current results list size or unknown value if the query is not open.
    */
   public integer size();
   
   /**
    * Progress-compatible function that returns the 1-based index of the
    * current row in the result set. This is the index of the entry at or
    * before which the cursor currently is positioned.
    *
    * @return  Unknown value if the query is not open or result set is empty.
    *          1 if the query is positioned before the first record.
    *          A value 1 greater than the number of rows in the query result
    *          set if the query is positioned beyond the last record.
    *          Otherwise returns the number of rows in the query result set. 
    *
    */
   @LegacyAttribute(name = "CURRENT-RESULT-ROW")
   public integer currentRow();
   
   /**
    * Get the 1-based index of the current row in the result set.  This is
    * the index of the entry at or before which the cursor currently is
    * positioned.
    *
    * @return  Current row or the unknown value if the current row cannot be
    *          determined.  The current row cannot be determined if the
    *          results list is empty, or if the cursor currently is in
    *          backward scroll mode.
    */
   public integer currentRowImpl();
   
   /**
    * Indicate whether the cursor has run off one or the other end of the
    * associated query's list of available results.  If <code>true</code>,
    * this indicates that the query cannot produce any more results in the
    * current scroll direction.
    *
    * @return  <code>true</code> if the cursor is off either end of its query's results list.
    */
   @LegacyAttribute(name = "QUERY-OFF-END")
   public logical isOffEnd();
   
   /**
    * Indicate whether the cursor has run off one or the other end of the
    * associated query's list of available results.  If <code>true</code>,
    * this indicates that the query cannot produce any more results in the
    * current scroll direction.
    *
    * @return  <code>true</code> if the cursor is off either end of its query's results list.
    */
   public boolean _isOffEnd();
   
   /**
    * Get the off-end status of this query, which indicates whether the query
    * has run off either end of its results.
    *
    * @return  One of the {@link OffEnd} constants <code>NONE</code>,
    *          <code>FRONT</code>, or <code>BACK</code>.
    */
   public OffEnd getOffEnd();
   
   /**
    * Indicate whether this query preselects all of its results.
    *
    * @return  <code>true</code> if the query preselects its results;
    *          <code>false</code> if the query's results are dynamically
    *          navigated.
    */
   public boolean isPreselect();
   
   /**
    * Indicate whether this query is a simple RECID/ROWID lookup FIND query. This has implications as to
    * whether a 7254 error will be raised in the event this FIND is nested within a function called within
    * another query's WHERE clause.
    * 
    * @return  {@code true} if this is a RECID/ROWID lookup FIND query, else {@code false}. This default
    *          implementation returns {@code false}.
    */
   public default boolean isFindByRowid()
   {
      return false;
   }
   
   /**
    * Indicate whether this query is a preselect query by its nature.
    *
    * @return  <code>true</code>.
    */
   public boolean isNativelyPreselect();
   
   /**
    * Is this query set to fetch the next record after a reposition?
    *
    * @return  <code>true</code> if set to fetch after reposition, else <code>false</code>.
    */
   public boolean isFetchOnReposition();
   
   /**
    * Set this query to automatically fetch the next record after a reposition, or turn this feature off.
    *
    * @param   enable
    *          <code>true</code> to enable automatic fetching;
    *          <code>false</code> to disable.
    */
   public void setFetchOnReposition(boolean enable);
   
   /**
    * Register a listener to receive notifications reposition events for this query.
    *
    * @param   listener
    *          Reposition listener to be registered.
    */
   public void addRepositionListener(RepositionListener listener);
   
   /**
    * Unregister a listener that was receiving notifications on reposition events for this query.
    *
    * @param   listener
    *          Reposition listener to be unregistered.
    */
   public void removeRepositionListener(RepositionListener listener);
   
   /**
    * Notify all registered listeners that query is repositioned or closed.
    * 
    * @param   closed
    *          A <code>true</code> value will inform all listeners that the query was explicitly closed.
    * @param   error
    *          <code>true</code> if an error happened during reposition.
    * @param   targetRepositionRow
    *          Row used as the target for reposition. If it was deleted, reposition with fetching
    *          may end up on a different row.
    */
   public void notifyRepositionListeners(boolean closed, boolean error, int targetRepositionRow);
   
   /**
    * Indicate to this query that whether it is associated with a browse widget or not.
    *
    * @param   browsed
    *          <code>true</code> to indicate the query has an associated
    *          browse widget, else <code>false</code>.
    */
   public void setBrowsed(boolean browsed);
   
   /**
    * Is this query associated with a browse widget or not?
    *
    * @return  <code>true</code> if the query has an associated browse widget,
    */
   public boolean isBrowsed();
   
   /**
    * Indicate whether this query stands alone, or is the component of
    * another query, or is wrapped by a query wrapper.
    * 
    * @return  <code>true</code> if standalone, else <code>false</code>.
    */
   public boolean isStandalone();
   
   /**
    * Change the standalone nature of this query.  A query is standalone by
    * default, but can be changed to non-standalone by the wrapper or
    * container which contains it.
    * 
    * @param   standalone
    *          <code>true</code> to set query as standalone;
    *          <code>false</code> to set query as contained.
    */
   public void setStandalone(boolean standalone);
   
   /**
    * Clean up resources associated with this query when its scope ends.
    */
   public void cleanup();
   
   /**
    * Conversion of QUERY-CLOSE() method (KW_QRY_CLOS).
    *
    * Closes a query object.
    *
    * @return  <code>true</code> if QUERY-CLOSE() succeeds, else <code>false</code>.
    */
   @LegacyMethod(name = "QUERY-CLOSE")
   public logical queryClose();
   
   /**
    * Conversion of REPOSITION-BACKWARD() method (KW_REPOS_B).
    *
    * Moves a query object's result list pointer backward a particular number of rows.
    *
    * @return  <code>true</code> if REPOSITION-BACKWARD() succeeds, else <code>false</code>.
    */
   @LegacyMethod(name = "REPOSITION-BACKWARD")
   public logical queryBackward(int rows);
   
   /**
    * Conversion of REPOSITION-BACKWARD() method (KW_REPOS_B).
    *
    * Moves a query object's result list pointer backward a particular number of rows.
    *
    * @return  <code>true</code> if REPOSITION-BACKWARD() succeeds,
    *          else <code>false</code>.
    */
   @LegacyMethod(name = "REPOSITION-BACKWARD")
   public logical queryBackward(NumberType rows);
   
   /**
    * Conversion of REPOSITION-FORWARD() method (KW_REPOS_F).
    *
    * Moves a query object's result list pointer forward a particular number
    * of rows.
    *
    * @return  <code>true</code> if REPOSITION-FORWARD() succeeds,
    *          else <code>false</code>.
    */
   @LegacyMethod(name = "REPOSITION-FORWARD")
   public logical queryForward(int rows);

   /**
    * Conversion of REPOSITION-FORWARD() method (KW_REPOS_F).
    *
    * Moves a query object's result list pointer forward a particular number
    * of rows.
    *
    * @return  <code>true</code> if REPOSITION-FORWARD() succeeds,
    *          else <code>false</code>.
    */
   @LegacyMethod(name = "REPOSITION-FORWARD")
   public logical queryForward(NumberType rows);

   /**
    * Conversion of REPOSITION-TO-ROW() method (KW_REPOS_2R).
    *
    * Moves a query object's result list pointer to the row corresponding to the specified
    * sequence number.
    *
    * @param   n
    *          An integer expression representing the sequence number.
    *
    * @return  <code>true</code> if REPOSITION-TO-ROW() succeeds,
    *          else <code>false</code>.
    */
   @LegacyMethod(name = "REPOSITION-TO-ROW")
   public logical queryReposition(int n);

   /**
    * Conversion of REPOSITION-TO-ROW() method (KW_REPOS_2R).
    *
    * Moves a query object's result list pointer to the row corresponding to the specified
    * sequence number.
    *
    * @param   n
    *          An integer expression representing the sequence number.
    *
    * @return  <code>true</code> if REPOSITION-TO-ROW() succeeds,
    *          else <code>false</code>.
    */
   @LegacyMethod(name = "REPOSITION-TO-ROW")
   public logical queryReposition(NumberType n);

   /**
    * Conversion of REPOSITION-TO-ROWID() method (KW_REPOS_2I).
    *
    * Reposition the cursor such that a request to retrieve the next result
    * will retrieve the result which matches the specified array of primary
    * key IDs.  A request to retrieve the previous result will retrieve the
    * result immediately previous to this, if any, in the results list.
    *
    * @param   id1
    *          A primary key ID, representing the target record (in the case
    *          of a join, this ID is associated with the left-most record in
    *          the join).
    * @param   joinIDs
    *          All remaining primary key IDs, if any, arranged from left to
    *          right to coincide with the records being joined by the
    *          underlying query.
    *
    * @return  <code>true</code> if REPOSITION-TO-ROWID() succeeds,
    *          else <code>false</code>.
    */
   @LegacyMethod(name = "REPOSITION-TO-ROWID")
   public logical queryRepositionByID(rowid id1, rowid...joinIDs);

   /**
    * Conversion of REPOSITION-TO-ROWID() method (KW_REPOS_2I).
    *
    * Reposition the cursor such that a request to retrieve the next result
    * will retrieve the result which matches the specified array of primary
    * key IDs.  A request to retrieve the previous result will retrieve the
    * result immediately previous to this, if any, in the results list.
    *
    * @param   id1
    *          A primary key ID, representing the target record (in the case
    *          of a join, this ID is associated with the left-most record in
    *          the join).
    * @param   joinIDs
    *          The list of IDs, starting with the primary key ID representing the target record, while 
    *          all remaining primary key IDs, if any, arranged from left to right to coincide with the records 
    *          being joined by the underlying query.
    *
    * @return  <code>true</code> if REPOSITION-TO-ROWID() succeeds,
    *          else <code>false</code>.
    */
   @LegacyMethod(name = "REPOSITION-TO-ROWID")
   public logical queryRepositionByID(rowid[] joinIDs);

   /**
    * Conversion of REPOSITION-TO-ROWID() method (KW_REPOS_2I).
    *
    * Reposition the cursor such that a request to retrieve the next result
    * will retrieve the result which matches the specified array of primary
    * key IDs.  A request to retrieve the previous result will retrieve the
    * result immediately previous to this, if any, in the results list.
    *
    * @param   rowId
    *          A character representation of this rowid.
    *
    * @return  <code>true</code> if REPOSITION-TO-ROWID() succeeds,
    *          else <code>false</code>.
    */
   @LegacyMethod(name = "REPOSITION-TO-ROWID")
   public default logical queryRepositionByID(character rowId)
   {
      UnimplementedFeature.todo("REPOSITION-TO-ROWID(CHARACTER) is not implemented");
      return new logical(false);
   }

   /**
    * Conversion of NUM-RESULTS attribute (KW_NUM_RES).
    *
    * Getter of NUM-RESULTS attribute
    *
    */
   @LegacyAttribute(name = "NUM-RESULTS")
   public integer getNumResults();

   /**
    * Compiles a predicate (query condition). This method is
    * the equivalent of <code>QUERY-PREPARE()</code> method from 4GL.
    * 
    * @param   predicate
    *          The predicate to be prepared by this query.
    * 
    * @return  true on success
    */
   @LegacyMethod(name = "QUERY-PREPARE")
   public logical prepare(String predicate);

   /**
    * Compiles a predicate (query condition). This method is
    * the equivalent of <code>QUERY-PREPARE()</code> method from 4GL.
    * 
    * @param   predicate
    *          The predicate to be prepared by this query.
    * 
    * @return  true on success
    */
   @LegacyMethod(name = "QUERY-PREPARE")
   public logical prepare(character predicate);

   /**
    * Opens a query object.
    * This method is the equivalent of <code>QUERY-OPEN()</code> method from 4GL.
    * <u>Note</u>: You must perform <code>prepare()</code> on a query 
    * object before you perform <code>queryOpen</code> on it. 
    * 
    * @return  true on success
    */
   @LegacyMethod(name = "QUERY-OPEN")
   public logical queryOpen();

   /**
    * Conversion of INDEX-INFORMATION attribute (KW_IDX_INFO).
    *
    * Getter of INDEX-INFORMATION attribute
    *
    * @return  A character string consisting of a comma-separated list of the index or
    *          indexes the query uses at the level of join specified.
    */
   @LegacyAttribute(name = "INDEX-INFORMATION")
   public character indexInformation();

   /**
    * Conversion of INDEX-INFORMATION attribute (KW_IDX_INFO).
    *
    * Getter of INDEX-INFORMATION attribute
    *
    * @param   n
    *          An integer expression that evaluates to the level of join for which you want
    *          index information.
    * 
    * @return  A character string consisting of a comma-separated list of the index or
    *          indexes the query uses at the level of join specified.
    */
   @LegacyAttribute(name = "INDEX-INFORMATION")
   public character indexInformation(int n);

   /**
    * Conversion of INDEX-INFORMATION attribute (KW_IDX_INFO).
    *
    * Getter of INDEX-INFORMATION attribute
    *
    * @param    n
    *           An integer expression that evaluates to the level of join for which you want index
    *           information.
    *
    * @return   A character string consisting of a comma-separated list of the index or indexes 
    *           the query uses at the level of join specified.
    */
   @LegacyAttribute(name = "INDEX-INFORMATION")
   public character indexInformation(NumberType n);

   /**
    * Conversion of FORWARD-ONLY attribute (KW_FWD_ONLY).
    *
    * Getter of FORWARD-ONLY attribute.
    *
    * @return  current value of FORWARD-ONLY attribute.
    */
   @LegacyAttribute(name = "FORWARD-ONLY")
   public logical forwardOnly();

   /**
    * Conversion of FORWARD-ONLY attribute (KW_FWD_ONLY).
    *
    * Setter of FORWARD-ONLY attribute.
    *
    * @param   forwardOnly
    *          New value of FORWARD-ONLY attribute.
    */
   @LegacyAttribute(name = "FORWARD-ONLY", setter = true)
   public void changeForwardOnly(logical forwardOnly);

   /**
    * Conversion of FORWARD-ONLY attribute (KW_FWD_ONLY).
    *
    * Setter of FORWARD-ONLY attribute.
    *
    * @param   forwardOnly
    *          New value of FORWARD-ONLY attribute.
    */
   @LegacyAttribute(name = "FORWARD-ONLY", setter = true)
   public void changeForwardOnly(boolean forwardOnly);

   /**
    * Conversion of PREPARE_STRING attribute (KW_PREP_STR).
    *
    * Getter of PREPARE_STRING attribute.
    *
    * @return  current value of PREPARE_STRING attribute.
    */
   @LegacyAttribute(name = "PREPARE-STRING")
   public character prepareString();

   /**
    * Getter for the CACHE attribute.
    * 
    * @return   See above.
    */
   @LegacyAttribute(name = "CACHE")
   public integer getCache();
   
   /**
    * Setter for the CACHE attribute.
    * 
    * @param    n
    *           The cache value.
    */
   @LegacyAttribute(name = "CACHE", setter = true)
   public void setCache(integer n);
   
   /**
    * Setter for the CACHE attribute.
    * 
    * @param    n
    *           The cache value.
    */
   @LegacyAttribute(name = "CACHE", setter = true)
   public void setCache(long n);
   
   /**
    * Conversion of GET-NEXT method (KW_GET_NEXT).
    *
    * Moves a query object's result list pointer ahead one row.
    *
    * @return  <code>true</code> if the next record in the query is found. If the query is not
    *          open or the next record cannot be found (query is empty or the query result list
    *          pointer is on the last row), the method returns <code>false</code>. If the query
    *          object handle is invalid, the method returns the Unknown value (?).
    */
   @LegacyMethod(name = "GET-NEXT")
   public default logical getNext()
   {
      return logical.of(_getNext());
   }
   
   /**
    * Conversion of GET-NEXT method (KW_GET_NEXT), which returns a Java boolean, for internal usage.
    *
    * Moves a query object's result list pointer ahead one row.
    *
    * @return  <code>true</code> if the next record in the query is found. If the query is not
    *          open or the next record cannot be found (query is empty or the query result list
    *          pointer is on the last row), the method returns <code>false</code>.
    */
   public boolean _getNext();

   /**
    * Conversion of GET-NEXT method (KW_GET_NEXT).
    *
    * Moves a query object's result list pointer ahead one row.
    *
    * @param   lockType
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if the next record in the query is found. If the query is not
    *          open or the next record cannot be found (query is empty or the query result list
    *          pointer is on the last row), the method returns <code>false</code>. If the query
    *          object handle is invalid, the method returns the Unknown value (?).
    */
   @LegacyMethod(name = "GET-NEXT")
   public logical getNext(LockType lockType);

   /**
    * Conversion of GET-NEXT method (KW_GET_NEXT).
    *
    * Moves a query object's result list pointer ahead one row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if the next record in the query is found. If the query is not
    *          open or the next record cannot be found (query is empty or the query result list
    *          pointer is on the last row), the method returns <code>false</code>. If the query
    *          object handle is invalid, the method returns the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> has not valid internal value.
    */
   @LegacyMethod(name = "GET-NEXT")
   public logical getNext(long lock);

   /**
    * Conversion of GET-NEXT method (KW_GET_NEXT).
    *
    * Moves a query object's result list pointer ahead one row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if the next record in the query is found. If the query is not
    *          open or the next record cannot be found (query is empty or the query result list
    *          pointer is on the last row), the method returns <code>false</code>. If the query
    *          object handle is invalid, the method returns the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> has not valid internal value.
    */
   @LegacyMethod(name = "GET-NEXT")
   public logical getNext(NumberType lock);

   /**
    * Conversion of GET-NEXT method (KW_GET_NEXT).
    *
    * Moves a query object's result list pointer ahead one row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the next record in the query is found. If the query is not
    *          open or the next record cannot be found (query is empty or the query result list
    *          pointer is on the last row), the method returns <code>false</code>. If the query
    *          object handle is invalid, the method returns the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-NEXT")
   public logical getNext(long lock, long nowait);

   /**
    * Conversion of GET-NEXT method (KW_GET_NEXT).
    *
    * Moves a query object's result list pointer ahead one row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the next record in the query is found. If the query is not
    *          open or the next record cannot be found (query is empty or the query result list
    *          pointer is on the last row), the method returns <code>false</code>. If the query
    *          object handle is invalid, the method returns the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-NEXT")
   public logical getNext(long lock, NumberType nowait);

   /**
    * Conversion of GET-NEXT method (KW_GET_NEXT).
    *
    * Moves a query object's result list pointer ahead one row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the next record in the query is found. If the query is not
    *          open or the next record cannot be found (query is empty or the query result list
    *          pointer is on the last row), the method returns <code>false</code>. If the query
    *          object handle is invalid, the method returns the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-NEXT")
   public logical getNext(NumberType lock, long nowait);

   /**
    * Conversion of GET-NEXT method (KW_GET_NEXT).
    *
    * Moves a query object's result list pointer ahead one row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the next record in the query is found. If the query is not
    *          open or the next record cannot be found (query is empty or the query result list
    *          pointer is on the last row), the method returns <code>false</code>. If the query
    *          object handle is invalid, the method returns the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-NEXT")
   public logical getNext(NumberType lock, NumberType nowait);

   /**
    * Conversion of GET-PREV method (KW_GET_PREV).
    *
    * Moves a query object's result list pointer back one row.
    *
    * @return  <code>true</code> if the previous record in the query is found. If the query is
    *          not open or the previous record cannot be found (query is empty or the query
    *          result list pointer is on the first row), the method returns <code>false</code>.
    *          If the query object handle is invalid, the method returns the Unknown value (?).
    */
   @LegacyMethod(name = "GET-PREV")
   public logical getPrevious();

   /**
    * Conversion of GET-PREV method (KW_GET_PREV).
    *
    * Moves a query object's result list pointer back one row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if the previous record in the query is found. If the query is
    *          not open or the previous record cannot be found (query is empty or the query
    *          result list pointer is on the first row), the method returns <code>false</code>.
    *          If the query object handle is invalid, the method returns the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> has not valid internal value.
    */
   @LegacyMethod(name = "GET-PREV")
   public logical getPrevious(long lock);

   /**
    * Conversion of GET-PREV method (KW_GET_PREV).
    *
    * Moves a query object's result list pointer back one row.
    *
    * @param   lockType
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if the previous record in the query is found. If the query is
    *          not open or the previous record cannot be found (query is empty or the query
    *          result list pointer is on the first row), the method returns <code>false</code>.
    *          If the query object handle is invalid, the method returns the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> has not valid internal value.
    */
   @LegacyMethod(name = "GET-PREV")
   public logical getPrevious(LockType lockType);

   /**
    * Conversion of GET-PREV method (KW_GET_PREV).
    *
    * Moves a query object's result list pointer back one row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if the previous record in the query is found. If the query is
    *          not open or the previous record cannot be found (query is empty or the query
    *          result list pointer is on the first row), the method returns <code>false</code>.
    *          If the query object handle is invalid, the method returns the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> has not valid internal value.
    */
   @LegacyMethod(name = "GET-PREV")
   public logical getPrevious(NumberType lock);

   /**
    * Conversion of GET-PREV method (KW_GET_PREV).
    *
    * Moves a query object's result list pointer back one row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the previous record in the query is found. If the query is
    *          not open or the previous record cannot be found (query is empty or the query
    *          result list pointer is on the first row), the method returns <code>false</code>.
    *          If the query object handle is invalid, the method returns the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-PREV")
   public logical getPrevious(long lock, long nowait);

   /**
    * Conversion of GET-PREV method (KW_GET_PREV).
    *
    * Moves a query object's result list pointer back one row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the previous record in the query is found. If the query is
    *          not open or the previous record cannot be found (query is empty or the query
    *          result list pointer is on the first row), the method returns <code>false</code>.
    *          If the query object handle is invalid, the method returns the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-PREV")
   public logical getPrevious(NumberType lock, long nowait);

   /**
    * Conversion of GET-PREV method (KW_GET_PREV).
    *
    * Moves a query object's result list pointer back one row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the previous record in the query is found. If the query is
    *          not open or the previous record cannot be found (query is empty or the query
    *          result list pointer is on the first row), the method returns <code>false</code>.
    *          If the query object handle is invalid, the method returns the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-PREV")
   public logical getPrevious(long lock, NumberType nowait);

   /**
    * Conversion of GET-PREV method (KW_GET_PREV).
    *
    * Moves a query object's result list pointer back one row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the previous record in the query is found. If the query is
    *          not open or the previous record cannot be found (query is empty or the query
    *          result list pointer is on the first row), the method returns <code>false</code>.
    *          If the query object handle is invalid, the method returns the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-PREV")
   public logical getPrevious(NumberType lock, NumberType nowait);

   /**
    * Conversion of GET-FIRST method (KW_GET_1ST).
    *
    * Moves a query object's result list pointer to the first row.
    *
    * @return  <code>true</code> if the first record in the query is found. If the query is not
    *          open or the first record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    */
   @LegacyMethod(name = "GET-FIRST")
   public logical getFirst();

   /**
    * Conversion of GET-FIRST method (KW_GET_1ST).
    *
    * Moves a query object's result list pointer to the first row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if the first record in the query is found. If the query is not
    *          open or the first record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> has not valid internal value.
    */
   @LegacyMethod(name = "GET-FIRST")
   public logical getFirst(long lock);

   /**
    * Conversion of GET-FIRST method (KW_GET_1ST).
    *
    * Moves a query object's result list pointer to the first row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if the first record in the query is found. If the query is not
    *          open or the first record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> has not valid internal value.
    */
   @LegacyMethod(name = "GET-FIRST")
   public logical getFirst(NumberType lock);

   /**
    * Conversion of GET-FIRST method (KW_GET_1ST).
    *
    * Moves a query object's result list pointer to the first row.
    *
    * @param   lockType
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if the first record in the query is found. If the query is not
    *          open or the first record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> has not valid internal value.
    */
   @LegacyMethod(name = "GET-FIRST")
   public logical getFirst(LockType lockType);

   /**
    * Conversion of GET-FIRST method (KW_GET_1ST).
    *
    * Moves a query object's result list pointer to the first row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the first record in the query is found. If the query is not
    *          open or the first record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-FIRST")
   public logical getFirst(long lock, long nowait);

   /**
    * Conversion of GET-FIRST method (KW_GET_1ST).
    *
    * Moves a query object's result list pointer to the first row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the first record in the query is found. If the query is not
    *          open or the first record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-FIRST")
   public logical getFirst(NumberType lock, long nowait);

   /**
    * Conversion of GET-FIRST method (KW_GET_1ST).
    *
    * Moves a query object's result list pointer to the first row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the first record in the query is found. If the query is not
    *          open or the first record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-FIRST")
   public logical getFirst(long lock, NumberType nowait);

   /**
    * Conversion of GET-FIRST method (KW_GET_1ST).
    *
    * Moves a query object's result list pointer to the first row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the first record in the query is found. If the query is not
    *          open or the first record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-FIRST")
   public logical getFirst(NumberType lock, NumberType nowait);

   /**
    * Conversion of GET-LAST method (KW_GET_LAST).
    *
    * Moves a query object's result list pointer to the last row.
    *
    * @return  <code>true</code> if the last record in the query is found. If the query is not
    *          open or the last record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    */
   @LegacyMethod(name = "GET-LAST")
   public logical getLast();

   /**
    * Conversion of GET-LAST method (KW_GET_LAST).
    *
    * Moves a query object's result list pointer to the last row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if the last record in the query is found. If the query is not
    *          open or the last record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> has not valid internal value.
    */
   @LegacyMethod(name = "GET-LAST")
   public logical getLast(long lock);

   /**
    * Conversion of GET-LAST method (KW_GET_LAST).
    *
    * Moves a query object's result list pointer to the last row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if the last record in the query is found. If the query is not
    *          open or the last record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> has not valid internal value.
    */
   @LegacyMethod(name = "GET-LAST")
   public logical getLast(NumberType lock);

   /**
    * Conversion of GET-LAST method (KW_GET_LAST).
    *
    * Moves a query object's result list pointer to the last row.
    *
    * @param   lockType
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if the last record in the query is found. If the query is not
    *          open or the last record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> has not valid internal value.
    */
   @LegacyMethod(name = "GET-LAST")
   public logical getLast(LockType lockType);

   /**
    * Conversion of GET-LAST method (KW_GET_LAST).
    *
    * Moves a query object's result list pointer to the last row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the last record in the query is found. If the query is not
    *          open or the last record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-LAST")
   public logical getLast(long lock, long nowait);

   /**
    * Conversion of GET-LAST method (KW_GET_LAST).
    *
    * Moves a query object's result list pointer to the last row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the last record in the query is found. If the query is not
    *          open or the last record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-LAST")
   public logical getLast(NumberType lock, long nowait);

   /**
    * Conversion of GET-LAST method (KW_GET_LAST).
    *
    * Moves a query object's result list pointer to the last row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the last record in the query is found. If the query is not
    *          open or the last record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-LAST")
   public logical getLast(long lock, NumberType nowait);

   /**
    * Conversion of GET-LAST method (KW_GET_LAST).
    *
    * Moves a query object's result list pointer to the last row.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if the last record in the query is found. If the query is not
    *          open or the last record cannot be found (query is empty), the method returns
    *          <code>false</code>. If the query object handle is invalid, the method returns
    *          the Unknown value (?).
    *
    * @throws  IllegalArgumentException
    *          if <code>lock</code> or <code>nowait</code> have not valid internal values.
    */
   @LegacyMethod(name = "GET-LAST")
   public logical getLast(NumberType lock, NumberType nowait);

   /**
    * Conversion of GET-CURRENT() method (KW_GET_CUR).
    *
    * Refetches the current record or records associated with the query.
    *
    * @return  <code>true</code> if GET-CURRENT() succeeds, else <code>false</code>.
    */
   @LegacyMethod(name = "GET-CURRENT")
   public logical getCurrent();

   /**
    * Conversion of GET-CURRENT() method (KW_GET_CUR).
    *
    * Refetches the current record or records associated with the query.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if GET-CURRENT() succeeds, else <code>false</code>.
    */
   @LegacyMethod(name = "GET-CURRENT")
   public logical getCurrent(long lock);

   /**
    * Conversion of GET-CURRENT() method (KW_GET_CUR).
    *
    * Refetches the current record or records associated with the query.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    *
    * @return  <code>true</code> if GET-CURRENT() succeeds, else <code>false</code>.
    */
   @LegacyMethod(name = "GET-CURRENT")
   public logical getCurrent(NumberType lock);

   /**
    * Conversion of GET-CURRENT() method (KW_GET_CUR).
    *
    * Refetches the current record or records associated with the query.
    *
    * @param   lockType
    *          Lock type
    *
    * @return  <code>true</code> if GET-CURRENT() succeeds, else <code>false</code>.
    */
   @LegacyMethod(name = "GET-CURRENT")
   public logical getCurrent(LockType lockType);

   /**
    * Conversion of GET-CURRENT() method (KW_GET_CUR).
    *
    * Refetches the current record or records associated with the query.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if GET-CURRENT() succeeds, else <code>false</code>.
    */
   @LegacyMethod(name = "GET-CURRENT")
   public logical getCurrent(long lock, long nowait);

   /**
    * Conversion of GET-CURRENT() method (KW_GET_CUR).
    *
    * Refetches the current record or records associated with the query.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if GET-CURRENT() succeeds, else <code>false</code>.
    */
   @LegacyMethod(name = "GET-CURRENT")
   public logical getCurrent(NumberType lock, long nowait);

   /**
    * Conversion of GET-CURRENT() method (KW_GET_CUR).
    *
    * Refetches the current record or records associated with the query.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if GET-CURRENT() succeeds, else <code>false</code>.
    */
   @LegacyMethod(name = "GET-CURRENT")
   public logical getCurrent(long lock, NumberType nowait);

   /**
    * Conversion of GET-CURRENT() method (KW_GET_CUR).
    *
    * Refetches the current record or records associated with the query.
    *
    * @param   lock
    *          SHARE-LOCK|EXCLUSIVE-LOCK|NO-LOCK
    * @param   nowait
    *          NO-WAIT
    *
    * @return  <code>true</code> if GET-CURRENT() succeeds, else <code>false</code>.
    */
   @LegacyMethod(name = "GET-CURRENT")
   public logical getCurrent(NumberType lock, NumberType nowait);
   
   /**
    * Setter for SKIP-DELETED-RECORD query attribute. 
    *
    * @param   on
    *          New value for the attribute.
    */
   @LegacyAttribute(name = "SKIP-DELETED-RECORD", setter = true)
   public void setSkipDeletedRecord(logical on);
   
   /**
    * Get value of SKIP-DELETED-RECORD attribute of the query.
    * 
    * @return  the value of SKIP-DELETED-RECORD attribute of the query.
    */
   @LegacyAttribute(name = "SKIP-DELETED-RECORD")
   public logical isSkipDeletedRecord();
   
   /**
    * Specifies the fields included in a record retrieval.
    *
    * @param dmo
    *        DMO proxy which defines the buffer for which the fields are specified.
    * @param fields
    *        The fields included in a record retrieval. If no fields are specified, only record
    *        identifiers are retrieved. No subscripts can be specified for extent fields.
    */
   public void include(DataModelObject dmo, String ... fields);

   /**
    * Specifies the fields excluded from a record retrieval.
    *
    * @param dmo
    *        DMO proxy which defines the buffer for which the fields are specified.
    * @param fields
    *        The fields excluded from a record retrieval. If no fields are specified, complete
    *        records are retrieved. No subscripts can be specified for extent fields.
    */
   public void exclude(DataModelObject dmo, String ... fields);

   /**
    * Deletes the current row of a query's result list. Implements the 4GL
    * DELETE-RESULT-LIST-ENTRY() method.
    *
    * @return <code>true</code> on success.
    */
   @LegacyMethod(name = "DELETE-RESULT-LIST-ENTRY")
   public logical deleteResultListEntry();
   
   /**
    * Deletes the current row of a query's result list. Implements the 4GL
    * DELETE-RESULT-LIST-ENTRY() method.
    *
    * @param  allowBetweenRows
    *         If <code>true</code> then the cursor can be positioned between rows (the next
    *         row will be deleted). <code>false</code> for conventional DELETE-RESULT-LIST-ENTRY()
    *         mode where the cursor should be positioned on a row (otherwise <code>false</code> is
    *         returned).
    *
    * @return <code>true</code> on success.
    */
   public logical deleteResultListEntry(boolean allowBetweenRows);
   
   /**
    * Creates an entry in the result list for the current row. Implements the 4GL
    * CREATE-RESULT-LIST-ENTRY() method. Created entry contains id(s) of the record(s) currently
    * located in the backing buffer(s).
    *
    * @return <code>true</code> on success.
    */
   @LegacyMethod(name = "CREATE-RESULT-LIST-ENTRY")
   public logical createResultListEntry();
   
   /**
    * Set the filter that handles parameters passed to the query. E.g. it can take input field
    * references and substitute them with snapshot values, if necessary.
    *
    * @param parameterFilter
    *        The filter that handles passed parameters.
    */
   public void setParameterFilter(ParameterFilter parameterFilter);
   
   /**
    * Releases the buffers controlled by this query. The position of this query is not affected.
    */
   public void releaseBuffers();
   
   /**
    * Adds a new constraint term to the where predicate of this query, effectively filtering out
    * any rows whose referenced field does not match the requested value. Semantically, the query
    * will select rows that match
    * <p>
    * {@code new-where := (fr = val) AND (old-query)}.
    * <p>
    * Note: The constraints are exclusive meaning that if constraints will be added for same
    * field of same buffer, the query will return an empty result because the field cannot be at
    * the same time equals to two different values.
    * <p>
    * Use {@link #clearDynamicFilters} to clean all dynamically added criteria and restore the
    * sorting order of the query to its original form.
    *
    * @param   fr
    *          A reference to field used as filtering criterion. Only the rows that matches the
    *          specified value for this field will be selected. Must not be {@code null}. 
    * @param   val
    *          The filtering value for this constraint. Can be {@code null} or {@code unknown}, in
    *          which case the SQL {@code null} value will be assumed. In this case the predicate
    *          will look like:
    *           <p>
    *          {@code new-where := (fr IS  NULL) AND (old-query)}
    * @param   format
    *          The format to be used when comparing values. The reason for this parameter is that
    *          for some datatype (ex: {@code decimal}) the on-screen value can be different from
    *          the database (because of rounding).
    *
    * @return  {@code true} if the filtering constraint was successfully added. If the field
    *          reference is not related to the buffer(s) of this query, {@code false} is returned.
    */
   public boolean addDynamicFilter(FieldReference fr, BaseDataType val, String format);
   
   /**
    * Clears any dynamically filters added at runtime. The query predicate will be restored to its
    * form from generated at conversion time. 
    */
   public void clearDynamicFilters();

   /**
    * Mark the query to retrieve the entire result set (useful for FILL operations).
    */
   public default void hintFullResults()
   {
      // no-op
   }
   
   /**
    * Adds a listener to be notified when this query is opened or closed.
    * <p> 
    * Note that this method is only called for dynamic queries only (for the moment).
    *  
    * @param   qel
    *          The listener to be notified.
    */
   public default void addQueryEventListener(QueryEventListener qel) {}
   
   /**
    * Notifies the registered QUERY-OPEN listeners that the even is about to happen.
    * 
    * @param    evaluate
    *           Flag indicating that the dynamic query must evaluate its dynamic calls (like DYNAMIC-FUNCTION)
    *           in the WHERE clause. 
    */
   public default void notifyQueryOpenListeners(boolean evaluate) {}
   
   /**
    * Notifies the registered QUERY-CLOSE listeners that the even is about to happen.
    */
   public default void notifyQueryCloseListeners() {}

   /**
    * Getter for the BASIC-LOGGING attribute.
    * 
    * @return   See above.
    */
   @LegacyAttribute(name = "BASIC-LOGGING")
   public default logical getBasicLogging()
   {
      UnimplementedFeature.missing("QUERY:BASIC-LOGGING");
      return new logical();
   }

   /**
    * Setter for the BASIC-LOGGING attribute.
    * 
    * @param    val
    *           Flag activating or deactivating the logging.
    */
   @LegacyAttribute(name = "BASIC-LOGGING", setter = true)
   public default void setBasicLogging(logical val)
   {
      UnimplementedFeature.missing("QUERY:BASIC-LOGGING");
   }

   /**
    * Setter for the BASIC-LOGGING attribute.
    * 
    * @param    val
    *           Flag activating or deactivating the logging.
    */
   @LegacyAttribute(name = "BASIC-LOGGING", setter = true)
   public default void setBasicLogging(boolean val)
   {
      UnimplementedFeature.missing("QUERY:BASIC-LOGGING");
   }
   
   /**
    * Informs the query that the next operations will be performed for filling browse rows, so it should not
    * return deleted rows/records (if argument is {@code true}). That is, temporarily overwrite the
    * SKIP-DELETED-RECORDS until the flag is turned off.
    * <p>
    * The default implementation does nothing.
    * 
    * @param   on
    *          if {@code true} the deleted rows will not be returned because the query is managed by the
    *          browse widget.
    */
   public default void setFillingBrowseRows(boolean on)
   {
   }
   
   /**
    * Test whether the flag was set.
    *
    * @return  {@code true} during the returning of rows for populating a browse widget.
    *
    * @see     #setFillingBrowseRows
    */
   public default boolean isFillingBrowseRows()
   {
      return false;
   }
   
   /**
    * Interface for receiving query events. 
    */
   public interface QueryEventListener
   {
      /**
       * Implement this method to receive the notification that the query IS ABOUT TO open.
       * 
       * @param    evaluate
       *           Flag indicating that the dynamic query must evaluate its dynamic calls (like DYNAMIC-FUNCTION)
       *           in the WHERE clause. 
       */
      public void onQueryOpen(boolean evaluate);
      
      /**
       * Implement this method to receive the notification that the query IS ABOUT TO close.
       */
      public void onQueryClose();
   }
   
   /** 
    * Get the recursive DATA-RELATION the query is to FILL for.  
    * @return the recursive DATA-RELATION the query is to FILL for
    */
   default DataRelation getDataRelation() 
   {
      return null;
   }

   /** 
    * Set the recursive DATA-RELATION the query is to FILL for.  
    * @param relation
    *       the recursive DATA-RELATION the query is to FILL for
    */
   default void setDataRelation(DataRelation relation) 
   {
   }
  
   /**
    * Interface for receiving query open events after the query has been opened. 
    */
   public interface QueryOpenedListener
   {
      /**
       * Implement this method to receive the notification that the query has just opened.
       */
      public void afterQueryOpen();
   }
   
   /**
    * Functional interface used with lambda expressions to defer evaluation of certain query
    * substitution parameter expressions. This allows proper error handling of these expressions.
    */
   @FunctionalInterface
   public interface Parameter
   {
      /**
       * Provide a value.
       * @return a value.
       */
      public Object resolve();
   }

   /**
    * Functional interface used with lambda expressions to late defer evaluation of certain query
    * substitution parameter expressions. This allows proper error handling of these expressions.
    * 
    * Emitted when the substitution is a child of contains. These arguments should always be character.
    */
   @FunctionalInterface
   public interface ParamResolver
   {
      /**
       * Provide a value.
       * @return a value.
       */
      public BaseDataType resolve();
   }
}