# 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();
       }
    }