QueryWrapper.java
/*
** Module : QueryWrapper.java
** Abstract : Proxy for concrete query implementations
**
** Copyright (c) 2005-2025, Golden Code Development Corporation.
**
** -#- -I- --Date-- --JPRM-- -----------------------------------Description-----------------------------------
** 001 ECF 20060430 @25885 Created initial version. Merged contents of
** AbstractQueryWrapper, CompoundQueryWrapper,
** PreselectQueryWrapper, and RandomAccessQuery-
** Wrapper. These classes are now obsolete. The
** merge was required because the same define
** query statement in Progress can be followed
** by many open query statements for that query;
** however, each open query may open a query of
** a different type than the previous one. Thus,
** a single wrapper type which supports all
** query types as delegates is required.
** 002 ECF 20060504 @25970 Added safety code. A default delegate query
** is automatically assigned upon construction,
** which has safe implementations of P2JQuery
** methods.
** 003 ECF 20060618 @27423 Change to assign() methods. Ensure query is
** set to scrolling upon assignment if the
** scrolling flag was previously set.
** 004 ECF 20061023 @30608 Added errorIfNull logic. P2JQuery interface
** now requires an implementation of the
** setErrorIfNull() method. The value set by the
** caller of this method is set into the query
** delegate, if one exists. If a delegate has
** not yet been assigned to the wrapper, the
** setting of this state in the delegate is
** deferred until a delegate is assigned.
** 005 ECF 20061027 @30754 Replaced Object with DataModelObject for DMO
** arguments to methods/constructors. Required
** for compile-time type safety.
** 006 ECF 20061102 @30960 Added support for reposition notification and
** auto-fetch features.
** 007 ECF 20061204 @31577 Implemented new P2JQuery methods to support
** browse.
** 008 NVS 20070502 @33345 Assigning a query should notify all listeners
** so that the related browse widget gets the
** notification and refreshes the display.
** 009 SIY 20070502 @33429 Added notifyRepositionListeners() method.
** Changed assignImpl() to use this new method.
** Minor cleanups in docs.
** 010 ECF 20070716 @34508 Added cleanup infrastructure. Wrapper is
** registered with TM at construction. At end of
** scope, cleanup is delegated to wrapped query.
** This ensures delegate does not clean up too
** early, since delegate may be assigned at a
** more deeply nested scope than those at which
** the wrapper can be used.
** 011 SIY 20070726 @34706 Helper method for explicit notification
** invocations.
** 012 ECF 20080202 @37005 Changed constructor signature. Added argument
** to indicate whether delegate query is a
** scrolling query. This allows us to avoid an
** ugly, anonymous initializer in converted code
** which does nothing more than invoke the
** setScrolling() method. Also, automatically
** invoked delegate's open() method when a
** PreselectQuery delegate is assigned.
** 013 ECF 20080509 @38244 Fixed assignImpl(). Removed notification to
** reposition listeners. This is handled from
** the delegate's open() method, which is now
** part of P2JQuery and is called when the
** delegate is assigned.
** 014 ECF 20080509 @38253 Fixed regression introduced by #013 (@38244).
** assignImpl() must not call open() for a
** multi-table query, since this will trigger
** execution of the query too early. Deprecated
** notifyListeners(), which should be replaced
** in business logic with open().
** 015 ECF 20080512 @38495 Changed setScrolling(). Do not process method
** body more than once.
** 016 SVL 20080604 @38533 Modified according to the new P2JQuery
** interface.
** 017 ECF 20080729 @39327 Added rowid support. Refactored reposition*()
** methods.
** 018 ECF 20081106 @40325 Added _isOffEnd(). Required by P2JQuery
** interface change.
** 019 CA 20081210 @40840 Implemented CLOSE QUERY statement. On close,
** it must notify all browse widgets to reset
** their state.
** 020 CA 20081211 @40860 Fixed regression introduced by H019: the
** delegate needs to be explicitly closed, not
** cleaned.
** 021 CA 20090227 @41389 Added WrappedResources.isUnknown method; this
** implementation returns false.
** 022 SIY 20090306 @41425 Close delegate if new one is assigned. This is
** necessary to properly notify underlying browse
** when they are associated with query.
** 023 ECF 20090312 @42981 Implemented getTableCount(). Supports NUM-BUFFERS
** query handle attribute. Changed some integer
** parameters to recids. Use parameterized form of
** WeakList.
** 024 SVL 20090730 @43446 Removed open() call from assign(). It should be
** called externally.
** 025 CA 20090731 @43469 Register the query for off-end listener
** registration after block initialization (done
** only for block types FOR and FOR EACH). Added
** getOffEndListeners, which returns a list of all
** off-end listeners for all used buffers.
** 026 SVL 20091030 @44289 Added getOffEnd() function to QueryWrapper and
** DefaultDelegate in order to support API change
** into P2JQuery.
** 027 SVL 20111111 presortDelegate checks that delegate is an
** instance of PresortDelegate (rather than
** PresortQuery).
** 028 VMN 20130207 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)
** and attributes
** NUM-RESULTS (KW_NUM_RES)
** 029 OM 20130212 Added implementation stubs for some dynamic methods.
** 030 VMN 20130213 Added support for attributes
** INDEX-INFORMATION (KW_IDX_INFO)
** FORWARD-ONLY (KW_FWD_ONLY)
** PREPARE_STRING (KW_PREP_STR)
** 031 VMN 20130219 Added support for attributes
** IS-OPEN (KW_IS_OPEN)
** 032 CA 20130221 Added ADM-DATA, UNIQUE-ID and chaining support.
** 033 OM 20130304 Refactored isValid and isUnknown of WrappedResource to valid
** and unknown.
** 034 VMN 20130306 Added addBuffer(handle bufHandle) and 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)
** Implemented
** getFirst(),getNext(),getLast(),getPrevious(),getCurrent()
** 035 CA 20130311 Added bufferHandle(integer).
** 036 VMN 20130311 Implemented queryClose, queryForward,
** queryReposition, queryRepositionByID,
** Delegating methods
** 037 VMN 20130312 Corrected conversion and runtime for
** REPOSITION-TO-ROW (KW_REPOS_2R)
** 038 CA 20130315 Added missing INDEX-INFORMATION API.
** 039 OM 20130320 Added implementation for ResultListHandler interface.
** 040 VMN 20130321 Corrected conversion and runtime for
** NUM-BUFFERS attribute(KW_NUM_BUFF)
** 041 CA 20130322 Added missing queryForward(integer) API.
** 042 SVL 20130325 Added include and exclude functions.
** 043 CA 20130603 resourceDelete must return a boolean value.
** 044 CA 20130927 Removed unknown() API, as by default the resource is known.
** 045 ECF 20130405 Moved createQuery static methods here from AbstractQuery.
** Cleaned up some documentation.
** 046 CA 20131024 Implemented runtime for the QUERY resource (static or dynamic).
** 047 ECF 20131028 Import change.
** 048 SVL 20131203 Changes caused by renaming of Nameable.get/setName to Nameable.name.
** 049 CA 20131123 Removed some interfaces which are implemented by HandleChain. Query
** cleanup must be performed only when the query gets explicitly or
** implicitly deleted.
** 050 SVL 20140430 Close the query when the external [persistent] procedure in which the
** query was opened is deleted. Call assignImpl() in prepare().
** 051 SVL 20140604 Added support for INDEX-INFORMATION.
** 052 SVL 20140909 Added isNativelyPreselect. Fixed reset of fetchOnReposition.
** 053 ECF 20141124 Added queryBackward methods.
** 054 OM 20150205 Queries do not need to be unregistered from DynamicQueryHelper.
** 055 SVL 20150218 Set fetchOnReposition to true for browsed queries on query
** reassignment.
** 056 SVL 20150305 Add buffers to the buffers array in order to make bufferHandle
** work properly. Consider query "is not open" if it is closing.
** Use force handle assignment in bufferHandle (ignoring pending
** errors).
** 057 SVL 20150331 Added deleteResultListEntry(boolean).
** 058 SVL 20150722 Updated notifyRepositionListeners signature.
** 059 ECF 20150801 Added setIterationType variant and optimize method.
** 060 SVL 20150821 Added isScrolling, removeRepositionListener, isBrowsed, getName.
** 061 OM 20150915 Added stub for SKIP-DELETED-RECORD attribute.
** 062 OM 20151029 Added minimal runtime support for SKIP-DELETED-RECORD attribute.
** 063 SVL 20151118 Static queries are registered at the procedure in which they were
** defined. Dynamic queries are closed when the scope of an underlying
** buffer ends.
** 064 ECF 20160106 Fixed close method to not reset to the default delegate, since the
** query can be re-opened and used again.
** 065 EVL 20160217 Clean up comments from symbols invalid for Solaris to compile.
** 066 SVL 20160314 Added setParameterFilter.
** 067 SVL 20160721 Set fetchOnReposition for browsed queries in open() too (for query
** reopen case).
** 068 ECF 20160725 Added setExternalBuffers method and new P2JQuery methods.
** 069 GES 20160804 Switched from WhereExpression to lambda usage.
** 070 CA 20161012 Fixed scope processing when the query is from a persistent
** procedure, and is part of a QUERY resource.
** 071 SVL 20161108 Do not open query on PREPARE.
** 072 HC 20170127 Fixed REPOSITION-FORWARD and REPOSITION-BACKWARD to return the
** value based on whether the new cursor position is "off-end".
** SVL 20170126 Added bufferHandle(), changed signature of
** queryForward/queryBackward.
** OM 20170209 Added return value for repositioning methods.
** 073 ECF 20171002 getNumResults returns unknown value if not scrolling.
** 074 GES 20171207 Removed forced version of assign().
** 075 OM 20171129 releaseBuffers() is implemented from P2JQuery.
** 076 ECF 20180201 Removed optimize method.
** 077 OM 20180515 Added dynamic filters and dynamic sort.
** 078 SVL 20180901 Refactored dynamic sorting functions.
** OM 20180924 Filtering on decimal fields uses STRING(f, format) function.
** 079 OM 20181010 Clearing dynamic sorting failed when no sorting was active.
** 080 ECF 20181106 Added runtime support for {FIRST|LAST}-OF methods.
** 081 OM 20181206 Added QUERY readonly attribute for BUFFERs. Added support for dynamic
** evaluations.
** CA 20181220 Added REPOSITION-TO-ROWID(character) stub.
** 082 ECF 20190302 Renamed setExternalBuffers to addExternalBuffers and changed
** implementation, since it may be called multiple times on a query.
** 083 OM 20190228 Removed deleted buffers from dynamic queries.
** 084 SVL 20190320 Updated createResultListEntry.
** 085 OM 20190327 Renamed DataSource to avoid conflicts with DataSet source.
** 086 OM 20190611 Added support for substitution buffers for dynamic queries.
** 087 OM 20190720 Added repositionByID() for internal usage.
** CA 20190812 Changes to allow for mutable buffers; any API which receives a Buffer
** instance and is invoked from converted code must resolve the runtime
** instance before saving the instance.
** HC 20190823 When query is deleted it must be unassigned from browse.
** EVL 20190823 Fix for query reposition with dynamic browse too early query set.
** CA 20190913 REPOSITION must raise an ERROR condition if the query is not opened.
** 088 SVL 20191002 Suppress query off-end exception for all wrapped navigation
** statements like "q:get-next()" or "get next q".
** If the query is bound to a browse, then the
** query:CREATE/DELETE-RESULT-LIST-ENTRY calls are redirected to
** browse:CREATE/DELETE-RESULT-LIST-ENTRY.
** 089 CA 20191005 A query must know if it is dynamic, when closing.
** 090 SVL 20191114 Fixed undesirable release of buffers for browsed preselect queries.
** CA 20200110 A small improvement in resourceDelete.
** 091 RFB 20200312 Added asHandle() method for handling QUERY q:HANDLE
** CA 20200428 QUERY handle has all callback-procedure APIs.
** CA 20200503 Added QUERY:CACHE runtime stub.
** 092 ECF 20200906 New ORM implementation.
** 093 CA 20200624 Static query resources can have their underlying query delegate changed via
** QUERY-PREPARE.
** CA 20200918 INDEX-INFORMATION requires to interpret the 'execute' method for a dynamic query
** without evaluating the dynamic calls in the WHERE.
** Fixed multiple QUERY-OPEN() calls - must close the query before reopening.
** VVT 20210108 repositionByID() fixed to match 4gl behaviour: see #5038-39
** OM 20201120 Added OFF-END callback.
** OM 20210219 bufferHandle() accepts int64 expression parameters.
** CA 20210310 A dynamic predicate must set the default lock to NONE, instead of SHARE.
** SVL 20210413 Added query wrapper listeners. Do not create a new delegate for dynamically
** sorted compound queries.
** AIL 20210505 Implemented setBuffers(Object...).
** AIL 20210507 Added support for addBuffer(character) and addBuffer(String).
** ECF 20210511 Replaced DynamicTablesHelper.normalizeName with TextOps.rightTrimLower.
** CA 20210516 Implemented getRecordBuffers().
** CA 20210527 isOffEnd() will return unknown for any closed query, regardless if static or
** dynamic.
** ECF 20210723 Changed signature of delegate query close worker method.
** AL2 20210909 Added support for indexed reposition.
** CA 20210920 When a buffer is deleted, all related queries must be reset (their predicate and
** buffer list).
** CA 20210923 assign(CompoundQuery) must not reset the query. Removed the 'closing' flag.
** OM 20220112 Added implementation of SKIP-DELETED-RECORD attribute.
** CA 20220930 Refactored the callback invocation to be performed via a call-site and
** InvokeConfig, to allow caching of the resolved target.
** CA 20221006 UNIQUE-ID and ADM-DATA are kept as Java types instead of BDT. Refs #6827
** TJD 20220504 Upgrade do Java 11 minor changes - added deprecated annotation
** GES 20210501 Upgraded dataset parameter processing to match API changes.
** CA 20220909 When a query gets deleted and is set at the query buffers' 'lastQuery', remove
** the reference.
** CA 20221123 Static QUERY instances must not be added to SESSION:FIRST-QUERY chain.
** SVL 20230108 Improved performance by replacing some "for-each" loops with indexed "for" loops.
** CA 20230110 UNIQUE-ID is generated only when is read by the application.
** Cache the helper for ProcedureManager, ObjectOps and others (as needed), to reduce
** context-local lookup.
** HC 20230116 Replaced some handle usages with the actual wrapped resources for
** performance.
** SVL 20221215 Reflected API change for setQuery.
** CA 20230116 Avoid using handle.unwrap, handle.getReference or other BDT usage from within FWD
** runtime.
** HC 20230118 Eliminated some of the uses of String.toUpperCase and/or
** String.toLowerCase for performance.
** 094 IAS 20230405 Fixed FILL support for recursive DATA-RELATION
** 095 AL2 20230411 Notify query close listeners.
** 096 GBB 20230512 Logging methods replaced by CentralLogger/ConversionStatus.
** 097 CA 20230724 Further reduce context-local usage.
** 098 AD 20231108 Fixed inverse assignment of skipDeletedRecordDisposition in constructor.
** 099 ES 20231203 Added new setLenientOffEnd method.
** ES 20231212 Removed handleQueryOffEnd method and all of its usage.
** Set lenientOffEnd for for PreselectQuery and CompundQuery.
** 100 OM 20231004 Handling errors in QUERY-OPEN implementation instead of propagating the error.
** OM 20240110 Implicit queries cannot be deleted using delete object statements.
** 101 AL2 20240307 Mark the query to retrieve the entire result set (useful for FILL operations).
** 102 CA 20240320 Avoid BDTs within internal FWD runtime. Replaced iterators with Java 'for',
** where it applies.
** 103 CA 20240324 Use logical constants for TRUE, FALSE, UNKNOWN, within internal FWD runtime.
** 104 OM 20240401 The setSubstitutionBuffers() method used for configuring the substitution buffers
** of a dataset buffer now contains the code for collecting them.
** 105 ES 20240404 Overridden setIteration, isIteration, setPresort and isPresort methods.
** 106 CA 20240424 The buffer to which a DATA-SOURCE is attached needs to be available to the FILL
** query.
** 107 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.
** 108 DDF 20240527 Swapped call to recordOrShowError() with recordOrShowDatabaseError().
** DDF 20240528 Replaced recordOrShowError() in indexInformation().
** 109 CA 20240809 Avoid iterator usage, for performance improvement.
** 110 CA 20240918 Removed default methods from interfaces and moved them as concrete implementations,
** as default methods cause the Java metaspace to spike one order of magnitude.
** 111 DDF 20230711 Allow reposition only when the query is non-scrolling.
** DDF 20230712 Added setForwardOnly() method and originalScrolling property.
** DDF 20230713 Handle errors for setting the FORWARD-ONLY attribute on a query that is being
** browsed.
** DDF 20230717 Properly propagate scrolling in delegates.
** DDF 20230721 Fixed forwardOnly assignment in delegates. Scrolling should be propagated
** only once in delegate and replace originalScrolling usage.
** DDF 20230823 Errors should be thrown for dynamic queries and shown for static queries.
** DDF 20241021 Removed unnecessary boolean parameter and replaced recordOrShowDatabaseError()
** with recordOrShowError() where the error handling is different for static and
** dynamic queries.
** 112 OM 20241128 Multi-tenant runtime support: selected the proper persistence context, eventually
** based on [sharedDb] parameter.
** Implementation of [setMultiTenantAlternative] method.
** 113 AL2 20241205 Re-delegate from AdaptiveQuery to PreselectQuery when adding dynamic sorts.
** 114 CA 20250321 Added 'setCallback' overloads.
** 115 AL2 20250416 Added support for "forceDatabaseJoin".
** 116 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.*;
import java.util.function.*;
import java.util.logging.*;
import com.goldencode.p2j.persist.event.*;
import com.goldencode.p2j.persist.lock.*;
import com.goldencode.p2j.util.*;
import com.goldencode.p2j.util.ErrorManager;
import com.goldencode.p2j.util.UniqueIdGenerator.IdKind;
import com.goldencode.p2j.util.logging.*;
/**
* A delegating container implementation for {@link AbstractQuery}s. An
* instance of this class contains an instance of <code>AbstractQuery</code>,
* to which it delegates the work of all of its methods.
* <p>
* The purpose of this class is to support queries defined in Progress using
* the DEFINE QUERY statement. These may be defined once, but opened and
* closed multiple times. In the P2J implementation, a new instance of
* <code>AbstractQuery</code> is constructed each time a query is "opened"
* (i.e., an OPEN QUERY was issued in the pre-conversion code). Since a
* reference to the query may be held by many routines, the query's internal
* state must be updated when the query is opened or re-opened. This is
* accomplished by sharing a reference to an instance of this class, which
* always holds the most recently constructed, underlying query. Thus, since
* all routines are accessing the query via this container (i.e., essentially
* by proxy), they will always be accessing the correct, underlying query.
* When a new query is opened, the new <code>AbstractQuery</code> instance is
* stored in the wrapper via one of the <code>assign</code> method variants.
* <p>
* The public methods of this class may only be invoked if the underlying
* delegate query is of a type which implements a method of the same
* signature. Many methods are supported by {@link AbstractQuery}, which is
* the abstract base class of all concrete query implementations. However,
* certain methods are implemented only by particular implementations. These
* will fail with an <code>IllegalStateException</code> if invoked when the
* wrong type of delegate has been set.
* <p>
* When an instance of this class is first created, a no-op, default
* implementation of <code>P2JQuery</code> is assigned immediately. This
* ensures that at least those methods which are defined by the
* <code>P2JQuery</code> interface have a safe methods. However, this does
* not protect the caller from invoking methods which are unique to specific
* query types, if no safe delegate has first been assigned. This safety
* measure is intended to protect other runtime code which generically uses
* an instance of this class via the <code>P2JQuery</code> interface (such as
* <code>BrowseWidge</code> in the UI).
* <p>
* A query wrapped by this object may need to clean up resources when the
* wrapper goes out of scope. A cleaner object is registered with the
* transaction manager upon construction of the wrapper, at the next external
* scope. This scope assumes that a <code>QueryWrapper</code> is only
* instantiated as an instance member of a business logic class. This is the
* case for all converted Progress code.
*/
@LegacyResource(resource = LegacyResource.QUERY)
public final class QueryWrapper
extends HandleChain
implements P2JQuery,
ADMData,
UniqueID,
DynamicResource,
ResultListHandler,
CallbackProcedure
{
/** Logger */
private static final CentralLogger LOG = CentralLogger.get(QueryWrapper.class.getName());
/** Default delegate to use before a real one is assigned */
private static final P2JQuery DEFAULT_DELEGATE = new DefaultDelegate();
/** The {@code OFF-END} event string constant in upper case. */
private static final String OFF_END_EVENT = "OFF-END";
/** The call-site for the {@link #OFF_END_EVENT} event callback. */
private static final InvokeConfig OFF_END_CALL_SITE = new InvokeConfig();
/** Delegate query */
private P2JQuery delegate = null;
/** Original query type before any dynamic operations. */
private Class<? extends P2JQuery> originalQueryType = null;
/** Reposition listeners registered with the delegate query */
private final WeakList<RepositionListener> repoListeners = new WeakList<>();
/** Should delegate be a scrolling query? */
private boolean scrolling = false;
/** Should delegate be optimized using indexed reposition */
private boolean indexedReposition = false;
/** Should delegate's failed first/last/unique retrievals raise error? */
private boolean errorIfNull = true;
/** Should the next row of the delegate be fetched after a reposition? */
private boolean fetchOnReposition = false;
/** Is query associated with a UI browse widget? */
private boolean browsed = false;
/** Opened listeners registered to get the message about query has been opened. */
private final ArrayList<QueryOpenedListener> openedListeners = new ArrayList<>();
/** Query wrapper listeners. */
private Set<QueryWrapperListener> wrapperListeners;
/** Flag indicating if the query was explicitly closed or is not open. */
private boolean closed = true;
/** Current off-end state. Used to detect when off-end state was encountered and fire OFF-END callback. */
private boolean offEnd = false;
/** Flag indicating if the query has been advanced (via GET NEXT) to the next record. */
private boolean advanced = false;
/** Flag indicating if this query is dynamic. */
private boolean dynamic = false;
/** Enforce a database join when the optimizer will kick in. */
private boolean forceDatabaseJoin = false;
/**
* Flag indicating if the query's {@link #delegate} is dynamic. This can be true even for a static query
* resource.
*/
private boolean dynamicDelegate = false;
/** Corresponds ADM-DATA attribute. */
private String admData;
/** Corresponds UNIQUE-ID attribute. */
private Long uniqueID = null;
/** Corresponds FORWARD-ONLY attribute. */
private boolean forwardOnly = false;
/** Contains the prepare string set by {@link #prepare}. */
private String prepareString = null;
/** The set of buffers used by this dynamic query. */
private final ArrayList<Buffer> buffers = new ArrayList<>();
/** Check if this query is valid. */
private boolean valid = true;
/** Internal reference for the query's name. */
private final String qname;
/** If the cleaner is already registered as a finalizable for this wrapper. */
private boolean cleanerRegistered = false;
/**
* The initial disposition for the value of SKIP-DELETED-RECORD. It is {@code true} for normal queries and
* {@code false} for static browsed queries.
*/
private boolean skipDeletedRecordDisposition = true;
/**
* The list of substitution buffers. These are not the main buffers the query is iterating but
* may appear in SUBST nodes (as substitution). By default (when {@code null}), each buffer in a
* dynamic query must appear exactly one time in FOR clause.
*/
private List<Buffer> substBuffers = null;
/** External handler for create/delete result list entry methods. */
private ResultListHandler externalResultListHandler = null;
/** The only possible callback. {@code null} if not set.*/
private CallbackData callback = null;
/** The recursive DATA-RELATION the query is to FILL for */
private DataRelation relation = null;
/**
* Flags this query as an explicit query to allow the programmer to delete it. When a query is created
* implicitly, the programmer will not be able to delete it (err 12349), but the deletion of the object is
* performed automatically.
*/
private boolean explicit = true;
/**
* Constructor which creates a static query and sets query scrolling mode for all delegate
* queries assigned to this wrapper.
*
* @param name
* The legacy name of this query.
* @param scrolling
* {@code true} to set all delegate queries assigned to this wrapper to scrolling mode,
* else {@code false} to not use scrolling mode.
*
* @deprecated This method was kept only to make the code already compiled against previous revision of FWD
* work. Although the code is unchanged the runtime will attempt to use of this signature as
* chosen by linker instead of {@code QueryWrapper(String, boolean, String...)}.
*/
@Deprecated
public QueryWrapper(String name, boolean scrolling)
{
this(name, scrolling, new String[] {});
}
/**
* Constructor which creates a static query and sets query scrolling mode for all delegate
* queries assigned to this wrapper.
*
* @param name
* The legacy name of this query.
* @param scrolling
* {@code true} to set all delegate queries assigned to this wrapper to scrolling mode,
* else {@code false} to not use scrolling mode.
* @param browseNames
* The legacy name of any BROWSEs widgets which use this query.
*/
public QueryWrapper(String name, boolean scrolling, String... browseNames)
{
this(name, scrolling, false);
int brCount = browseNames.length;
skipDeletedRecordDisposition = brCount == 0;
if (brCount > 1)
{
for (int k = 0; k < brCount - 1; k++)
{
ErrorManager.recordOrShowError(3147, name, "");
// Cannot browse query <query> because query is already being browsed. (3147)
}
}
}
/**
* Constructor which sets query scrolling mode for all delegate queries assigned to this
* wrapper.
*
* @param name
* The legacy name of this query.
* @param scrolling
* <code>true</code> to set all delegate queries assigned to this wrapper to scrolling
* mode, else <code>false</code> to not use scrolling mode.
* @param dynamic
* Flag identifying a dynamic query.
*/
private QueryWrapper(String name, boolean scrolling, boolean dynamic)
{
super(dynamic, dynamic);
this.name = name;
this.qname = name;
this.dynamic = dynamic;
// Store a safe delegate until a real one is assigned.
this.delegate = DEFAULT_DELEGATE;
if (scrolling)
{
setScrolling();
}
TransactionManager.registerOffEndQuery(this);
}
/**
* Clear the current results from the query, so the same query instance can be executed again, without
* having to {@link #open() re-open} it.
*/
@Override
public void clearResults()
{
if (delegate != null)
{
delegate.clearResults();
}
}
/**
* Mark the query to retrieve the entire result set (useful for FILL operations).
*/
public void hintFullResults()
{
if (delegate != null)
{
delegate.hintFullResults();
}
}
/**
* Register the cleaner which closes the query when the external [persistent] procedure in
* which the query was opened is deleted.
*/
private void registerCleaner()
{
Finalizable cleaner = new Finalizable()
{
@Override
public void finished()
{
}
@Override
public void deleted()
{
if (!closed)
{
close();
}
}
@Override
public void iterate()
{
}
@Override
public void retry()
{
}
};
TransactionManager.registerTopLevelFinalizable(cleaner, true);
cleanerRegistered = true;
}
/**
* Dynamically creates a query in the specified widget pool and assign
* it to a handle.
* This method is the equivalent of <code>CREATE QUERY</code> from 4GL.
*
* @param hQuery
* The handle to assign the newly created query.
* @param widgetPool
* The name of the widget pool that contains the dynamic query. <code>null</code> if
* the unnamed pool must be used.
*/
public static void createQuery(handle hQuery, String widgetPool)
{
createQuery(hQuery, (widgetPool == null ? null : new character(widgetPool)));
}
/**
* Dynamically creates a query in the specified widget pool and assign
* it to a handle.
* This method is the equivalent of <code>CREATE QUERY</code> from 4GL.
*
* @param hQuery
* The handle to assign the newly created query.
* @param widgetPool
* The name of the widget pool that contains the dynamic query. <code>null</code> if
* the unnamed pool must be used.
*/
public static void createQuery(handle hQuery, character widgetPool)
{
// validate widget pool before anything else!!!
if (!WidgetPool.validWidgetPool(widgetPool))
{
return;
}
// create the query; use an empty string as its name
QueryWrapper res = new QueryWrapper("", true, true);
hQuery.assign(res);
res.addToPool(widgetPool);
}
/**
* Dynamically creates a query and assign it to a handle. This form of the
* method will create the object in the current default widget pool.
* This method is the equivalent of <code>CREATE QUERY</code> from 4GL.
*
* @param hQuery
* The handle to assign the newly created query.
*/
public static void createQuery(handle hQuery)
{
createQuery(hQuery, (character) null);
}
/**
* Dynamically creates a query in the specified widget pool.
*
* This method is the equivalent of <code>CREATE QUERY</code> from 4GL.
*
* @return the newly created query.
*/
public static QueryWrapper createQueryUnnamedPool()
{
// create the query; use an empty string as its name
QueryWrapper res = new QueryWrapper("", true, true);
res.addToPool(null);
return res;
}
/**
* Conversion of DYNAMIC attribute. Returns <code>true</code> if the buffer is dynamic.
*
* @return <code>true</code> if the resource is dynamic, <code>false</code> otherwise.
*/
@Override
public logical dynamic()
{
return logical.of(dynamic);
}
/**
* Conversion of DYNAMIC attribute. Returns <code>true</code> if the buffer is dynamic.
*
* @return <code>true</code> if the resource is dynamic, <code>false</code> otherwise.
*/
@Override
public boolean _dynamic()
{
return dynamic;
}
/**
* Assign a newly opened <code>CompoundQuery</code> instance as this
* container's active delegate query.
*
* @param delegate
* New delegate query.
*/
public void assign(CompoundQuery delegate)
{
// DO NOT RESET THE QUERY HERE!
assignImpl(delegate);
delegate.setLenientOffEnd(true);
}
/**
* Assign a newly opened <code>PreselectQuery</code> instance as this
* container's active delegate query.
*
* @param delegate
* New delegate query.
*/
public void assign(PreselectQuery delegate)
{
addBuffers(delegate, true);
assignImpl(delegate);
delegate.setLenientOffEnd(true);
}
/**
* Assign a newly opened <code>RandomAccessQuery</code> instance as this
* container's active delegate query.
*
* @param delegate
* New delegate query.
*/
public void assign(RandomAccessQuery delegate)
{
addBuffers(delegate, true);
assignImpl(delegate);
delegate.setLenientOffEnd(true);
}
/**
* Ensure that any <code>AbstractQuery</code> assigned to this wrapper is
* a scrolling query, to enable results list scrolling/repositioning. If
* a query is already assigned to this wrapper, invoke its
* <code>setScrolling</code> method immediately.
*/
public void setScrolling()
{
if (!scrolling)
{
scrolling = true;
if (delegate != null)
{
getDelegate().setScrolling();
}
}
}
/**
* Indicate whether this query was defined as SCROLLING.
*
* @return <code>true</code> if this query is scrolling.
*/
public boolean isScrolling()
{
return scrolling;
}
/**
* 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.
*/
@Override
public void setIterating(boolean iterating)
{
delegate.setIterating(iterating);
}
/**
* Indicate whether the delegate query is defined inside the scope of FOR EACH block.
*
* @return <code>true</code> if the query was defined inside a FOR EACH block.
*/
@Override
public boolean isIterating()
{
return delegate.isIterating();
}
/**
* Indicate whether the delegate query is of presort type.
*
* @return <code>true</code> if the query is of presort type..
*/
@Override
public boolean isPresort()
{
return delegate.isPresort();
}
/**
* Indicate whether the delegate 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.
*/
@Override
public void setPresort(boolean presort)
{
delegate.setPresort(presort);
}
/**
* 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.
*/
@Override
public void setForceDatabaseJoin(logical forceDatabaseJoin)
{
this.forceDatabaseJoin = forceDatabaseJoin.booleanValue();
if (delegate != null)
{
getDelegate().setForceDatabaseJoin(forceDatabaseJoin);
}
}
/**
* Check if the database join enforcing is active.
*
* @return {@code true} if the query will always use DB joins.
*/
@Override
public logical isForceDatabaseJoin()
{
return logical.of(this.forceDatabaseJoin);
}
/**
* Ensure that any <code>AbstractQuery</code> assigned to this wrapper is
* a optimized query using indexed reposition. This flag can be set only if
* the query is scrolling. An indexed reposition query can be repositioned
* to an unflushed record (one which was not in the database when the
* query was opened). Repositioning to such record will empty the result list.
*
* @throws ErrorConditionException
* if the underlying delegate is not scrolling.
*/
@Override
public void setIndexedReposition()
{
if (!indexedReposition)
{
setDelegateIndexedReposition();
indexedReposition = true;
}
}
/**
* Indicate whether this query is optimized using indexed reposition.
*
* @return <code>true</code> if this query is indexed reposition.
*/
@Override
public boolean isIndexedReposition()
{
return indexedReposition;
}
/**
* Open the prepared query delegate.
*/
public void open()
{
notifyBeforeOpenListeners();
this.closed = false;
this.advanced = false;
if (browsed)
{
fetchOnReposition = true;
delegate.setFetchOnReposition(true);
}
delegate.open();
if (!browsed && delegate.isNativelyPreselect())
{
delegate.releaseBuffers();
}
if (!(cleanerRegistered || dynamic || dynamicDelegate))
{
registerCleaner();
}
offEnd = delegate._isOffEnd();
}
/**
* Explicitly close the prepared query delegate.
*/
public void close()
{
notifyRepositionListeners(true, false, -1);
delegate.close(true);
this.fetchOnReposition = false;
this.closed = true;
// release the reference, if not valid
if (!valid)
{
delegate = null;
}
}
/**
* Reset the query (this does not close the query).
*/
@Override
public void resetQuery()
{
this.prepareString = null;
unregisterBufferRelatedQueries();
buffers.clear();
}
/**
* Get the number of tables joined by this query.
*
* @return Number of tables joined by this query.
*/
public int getTableCount()
{
return delegate.getTableCount();
}
/**
* Get all the off-end listeners associated with this query.
*
* @return the off-end listeners associated with this query.
*/
public ArrayList<QueryOffEndListener> getOffEndListeners()
{
return delegate.getOffEndListeners();
}
/**
* 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 query wrapper.
*/
public P2JQuery addExternalBuffers(DataModelObject... dmos)
{
delegate.addExternalBuffers(dmos);
return this;
}
/**
* 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.
*/
@Override
public P2JQuery setMultiTenantAlternative(String where,
Supplier<logical> whereExpr,
String sort,
Object[] args)
{
delegate.setMultiTenantAlternative(where, whereExpr, sort, args);
return this;
}
/**
* 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.
*/
@Override
public P2JQuery setMultiTenantAlternative(String where, Supplier<logical> whereExpr, String sort)
{
delegate.setMultiTenantAlternative(where, whereExpr, sort);
return this;
}
/**
* Set a mode on the underlying buffers such that setting a null record
* into a buffer may or may not result in an error condition. This applies
* only to <code>FIRST</code>, <code>LAST</code>, and <code>UNIQUE</code>
* iteration types.
* <p>
* If a query delegate has already been set, it is updated with the new
* setting immediately. The setting is remembered, such that any delegate
* assigned after this method is invoked will have this setting updated
* upon assignment to the query wrapper.
*
* @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)
{
this.errorIfNull = errorIfNull;
if (delegate != null)
{
getDelegate().setErrorIfNull(errorIfNull);
}
}
/**
* Add a joinable query to a compound query. If this is not the first
* component to be added to the query, its results will be joined to the
* immediately previous component by an inner join. This query will be
* iterated using the <code>NEXT</code> iteration type.
*
* @param query
* Query which will perform the fundamental work for this
* component when the compound query is iterated.
*
* @throws IllegalStateException
* if this method is invoked during an iteration cycle or if
* delegate is not an instance of <code>CompoundQuery</code>.
*
* @see #iterate
*/
public void addComponent(Joinable query)
{
compoundDelegate().addComponent(query);
}
/**
* Add a joinable query to a compound query, and specify the nature of
* the iteration which will be performed (first, last, next, etc.) on that
* component, when the compound query is iterated. If this is not the
* first component to be added to the query, its results will be joined to
* the immediately previous component by an inner join.
*
* @param query
* Query which will perform the fundamental work for this
* component when the compound query is iterated.
* @param iteration
* A {@link QueryConstants constant} indicating the type of work
* to be performed upon an iteration of the compound query. This
* parameter determines whether the underlying query will be asked
* to perform a first, last, next, previous, or unique record
* retrieval.
*
* @throws IllegalStateException
* if this method is invoked during an iteration cycle or if
* delegate is not an instance of <code>CompoundQuery</code>.
*
* @see #iterate
*/
public void addComponent(Joinable query, int iteration)
{
compoundDelegate().addComponent(query, iteration);
}
/**
* Add a joinable query to a compound query, and specify the nature of
* the iteration which will be performed (first, last, next, etc.) on that
* component, when the compound query is iterated. If this is not the
* first component to be added to the query, the type of join performed
* with the immediately previous component is determined by the value of
* <code>outer</code>.
*
* @param query
* Query which will perform the fundamental work for this
* component when the compound query is iterated.
* @param iteration
* A {@link QueryConstants constant} indicating the type of work
* to be performed upon an iteration of the compound query. This
* parameter determines whether the underlying query will be asked
* to perform a first, last, next, previous, or unique record
* retrieval.
* @param outer
* <code>true</code> if this component should be joined to the
* previously added component via a left outer join;
* <code>false</code> if an inner join is required. Note that
* adding an inner join component will cause any previously added
* components added as outer joins to be reset to inner joins.
*
* @throws IllegalStateException
* if this method is invoked during an iteration cycle or if
* delegate is not an instance of <code>CompoundQuery</code>.
*
* @see #iterate
*/
public void addComponent(Joinable query, int iteration, boolean outer)
{
compoundDelegate().addComponent(query, iteration, outer);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>no substitution parameters
* <li>share lock
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo, String where)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>no substitution parameters
* <li>share lock
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param indexInfo
* Index information string as it is returned by INDEX-INFORMATION.
* May be <code>null</code> if it is not an OPEN QUERY case or if
* you don't need debug information about selected indexes.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo, String where, String indexInfo)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, indexInfo);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>no substitution parameters
* <li>share lock
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param inverse
* DMO to which this query should join via a foreign relation.
* May be <code>null</code>.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
DataModelObject inverse)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, inverse);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>no substitution parameters
* <li>share lock
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param indexInfo
* Index information string as it is returned by INDEX-INFORMATION.
* May be <code>null</code> if it is not an OPEN QUERY case or if
* you don't need debug information about selected indexes.
* @param inverse
* DMO to which this query should join via a foreign relation.
* May be <code>null</code>.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
String indexInfo,
DataModelObject inverse)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, indexInfo, inverse);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>share lock
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param args
* Substitution parameters to be inserted into placeholders within
* the where clause.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo, String where, Object[] args)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, args);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>share lock
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param indexInfo
* Index information string as it is returned by INDEX-INFORMATION.
* May be <code>null</code> if it is not an OPEN QUERY case or if
* you don't need debug information about selected indexes.
* @param args
* Substitution parameters to be inserted into placeholders within
* the where clause.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo, String where, String indexInfo, Object[] args)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, indexInfo, args);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>share lock
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param inverse
* DMO to which this query should join via a foreign relation.
* May be <code>null</code>.
* @param args
* Substitution parameters to be inserted into placeholders within
* the where clause.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
DataModelObject inverse,
Object[] args)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, inverse, args);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>share lock
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param indexInfo
* Index information string as it is returned by INDEX-INFORMATION.
* May be <code>null</code> if it is not an OPEN QUERY case or if
* you don't need debug information about selected indexes.
* @param inverse
* DMO to which this query should join via a foreign relation.
* May be <code>null</code>.
* @param args
* Substitution parameters to be inserted into placeholders within
* the where clause.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
String indexInfo,
DataModelObject inverse,
Object[] args)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, indexInfo, inverse, args);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>no substitution parameters
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param lockType
* Lock type to apply to records retrieved by this component of
* the query.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
LockType lockType)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, lockType);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>no substitution parameters
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param indexInfo
* Index information string as it is returned by INDEX-INFORMATION.
* May be <code>null</code> if it is not an OPEN QUERY case or if
* you don't need debug information about selected indexes.
* @param lockType
* Lock type to apply to records retrieved by this component of
* the query.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
String indexInfo,
LockType lockType)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, indexInfo, lockType);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>no substitution parameters
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param inverse
* DMO to which this query should join via a foreign relation.
* May be <code>null</code>.
* @param lockType
* Lock type to apply to records retrieved by this component of
* the query.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
DataModelObject inverse,
LockType lockType)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, inverse, lockType);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>no substitution parameters
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param indexInfo
* Index information string as it is returned by INDEX-INFORMATION.
* May be <code>null</code> if it is not an OPEN QUERY case or if
* you don't need debug information about selected indexes.
* @param inverse
* DMO to which this query should join via a foreign relation.
* May be <code>null</code>.
* @param lockType
* Lock type to apply to records retrieved by this component of
* the query.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
String indexInfo,
DataModelObject inverse,
LockType lockType)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, indexInfo, inverse, lockType);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param args
* Substitution parameters to be inserted into placeholders within
* the where clause.
* @param lockType
* Lock type to apply to records retrieved by this component of
* the query.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
Object[] args,
LockType lockType)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, args, lockType);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param indexInfo
* Index information string as it is returned by INDEX-INFORMATION.
* May be <code>null</code> if it is not an OPEN QUERY case or if
* you don't need debug information about selected indexes.
* @param args
* Substitution parameters to be inserted into placeholders within
* the where clause.
* @param lockType
* Lock type to apply to records retrieved by this component of
* the query.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
String indexInfo,
Object[] args,
LockType lockType)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, indexInfo, args, lockType);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param inverse
* DMO to which this query should join via a foreign relation.
* May be <code>null</code>.
* @param args
* Substitution parameters to be inserted into placeholders within
* the where clause.
* @param lockType
* Lock type to apply to records retrieved by this component of
* the query.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
DataModelObject inverse,
Object[] args,
LockType lockType)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, inverse, args, lockType);
}
/**
* Add a component to a preselect query. The following defaults are used:
* <ul>
* <li>inner join
* <li><code>NEXT</code> iteration type
* </ul>
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param indexInfo
* Index information string as it is returned by INDEX-INFORMATION.
* May be <code>null</code> if it is not an OPEN QUERY case or if
* you don't need debug information about selected indexes.
* @param inverse
* DMO to which this query should join via a foreign relation.
* May be <code>null</code>.
* @param args
* Substitution parameters to be inserted into placeholders within
* the where clause.
* @param lockType
* Lock type to apply to records retrieved by this component of
* the query.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
String indexInfo,
DataModelObject inverse,
Object[] args,
LockType lockType)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo, where, indexInfo, inverse, args, lockType);
}
/**
* Add a component to a preselect query.
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param args
* Substitution parameters to be inserted into placeholders within
* the where clause.
* @param lockType
* Lock type to apply to records retrieved by this component of
* the query.
* @param iteration
* Iteration/retrieval mode for this component of the query. At
* this time, only <code>NEXT</code> is supported. Future
* support for <code>FIRST</code>, <code>LAST</code>, and
* <code>UNIQUE</code> is expected.
* @param outer
* <code>true</code> if an outer join is required. At this time,
* only inner joins are supported. Future support for outer
* joins is expected.
*
* @throws UnsupportedOperationException
* if <code>outer</code> is <code>true</code> (temporary);
* if <code>iteration</code> is not <code>NEXT</code> (temporary);
* if <code>dmo</code>'s associated database is different than
* that of a previously added component's database (cross-database
* preselect joins are not possible).
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
Object[] args,
LockType lockType,
int iteration,
boolean outer)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo,
where,
args,
lockType,
iteration,
outer);
}
/**
* Add a component to a preselect query.
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param indexInfo
* Index information string as it is returned by INDEX-INFORMATION.
* May be <code>null</code> if it is not an OPEN QUERY case or if
* you don't need debug information about selected indexes.
* @param args
* Substitution parameters to be inserted into placeholders within
* the where clause.
* @param lockType
* Lock type to apply to records retrieved by this component of
* the query.
* @param iteration
* Iteration/retrieval mode for this component of the query. At
* this time, only <code>NEXT</code> is supported. Future
* support for <code>FIRST</code>, <code>LAST</code>, and
* <code>UNIQUE</code> is expected.
* @param outer
* <code>true</code> if an outer join is required. At this time,
* only inner joins are supported. Future support for outer
* joins is expected.
*
* @throws UnsupportedOperationException
* if <code>outer</code> is <code>true</code> (temporary);
* if <code>iteration</code> is not <code>NEXT</code> (temporary);
* if <code>dmo</code>'s associated database is different than
* that of a previously added component's database (cross-database
* preselect joins are not possible).
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
String indexInfo,
Object[] args,
LockType lockType,
int iteration,
boolean outer)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo,
where,
indexInfo,
args,
lockType,
iteration,
outer);
}
/**
* Add a component to a preselect query.
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param inverse
* DMO to which this query should join via a foreign relation.
* May be <code>null</code>.
* @param args
* Substitution parameters to be inserted into placeholders within
* the where clause.
* @param lockType
* Lock type to apply to records retrieved by this component of
* the query.
* @param iteration
* Iteration/retrieval mode for this component of the query. At
* this time, only <code>NEXT</code> is supported. Future
* support for <code>FIRST</code>, <code>LAST</code>, and
* <code>UNIQUE</code> is expected.
* @param outer
* <code>true</code> if an outer join is required. At this time,
* only inner joins are supported. Future support for outer
* joins is expected.
*
* @throws UnsupportedOperationException
* if <code>outer</code> is <code>true</code> (temporary);
* if <code>iteration</code> is not <code>NEXT</code> (temporary);
* if <code>dmo</code>'s associated database is different than
* that of a previously added component's database (cross-database
* preselect joins are not possible).
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
DataModelObject inverse,
Object[] args,
LockType lockType,
int iteration,
boolean outer)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo,
where,
inverse,
args,
lockType,
iteration,
outer);
}
/**
* Add a component to a preselect query.
*
* @param dmo
* DMO proxy which defines buffer and record type.
* @param where
* HQL where clause. May be <code>null</code>.
* @param indexInfo
* Index information string as it is returned by INDEX-INFORMATION.
* May be <code>null</code> if it is not an OPEN QUERY case or if
* you don't need debug information about selected indexes.
* @param inverse
* DMO to which this query should join via a foreign relation.
* May be <code>null</code>.
* @param args
* Substitution parameters to be inserted into placeholders within
* the where clause.
* @param lockType
* Lock type to apply to records retrieved by this component of
* the query.
* @param iteration
* Iteration/retrieval mode for this component of the query. At
* this time, only <code>NEXT</code> is supported. Future
* support for <code>FIRST</code>, <code>LAST</code>, and
* <code>UNIQUE</code> is expected.
* @param outer
* <code>true</code> if an outer join is required. At this time,
* only inner joins are supported. Future support for outer
* joins is expected.
*
* @throws UnsupportedOperationException
* if <code>outer</code> is <code>true</code> (temporary);
* if <code>iteration</code> is not <code>NEXT</code> (temporary);
* if <code>dmo</code>'s associated database is different than
* that of a previously added component's database (cross-database
* preselect joins are not possible).
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addComponent(DataModelObject dmo,
String where,
String indexInfo,
DataModelObject inverse,
Object[] args,
LockType lockType,
int iteration,
boolean outer)
{
addBuffer((Buffer) dmo, true);
preselectDelegate().addComponent(dmo,
where,
indexInfo,
inverse,
args,
lockType,
iteration,
outer);
}
/**
* Add a client-side where expression to a preselect query. Each initial
* query result found by the server must be accepted by this expression
* before becoming a part of the query's final result set.
*
* @param whereExpr
* Client-side where clause expression. May not be
* <code>null</code>.
*
* @throws NullPointerException
* if <code>whereExpr</code> is <code>null</code>.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PreselectQuery</code>.
*/
public void addWhereExpression(Supplier<logical> whereExpr)
{
preselectDelegate().addWhereExpression(whereExpr);
}
/**
* Set the iteration type for the most recently added query component to a preselect query.
*
* @param iteration
* Retrieval mode from {@link QueryConstants}. Must not be FIRST or LAST (use
* {@link #setIterationType(int, String)} instead for these types.
*
* @throws IllegalStateException
* if no component has yet been added; or
* if delegate is not an instance of <code>PreselectQuery</code>.
* @throws IllegalArgumentException
* if <code>iteration</code> type is <code>FIRST</code> or <code>LAST</code>.
*/
public void setIterationType(int iteration)
{
preselectDelegate().setIterationType(iteration);
}
/**
* Set the iteration type for the most recently added query component to a preselect query.
*
* @param iteration
* Retrieval mode from {@link QueryConstants}.
* @param sort
* Order by clause which should be associated with the most recently added query
* component. Must be non-<code>null</code> for iteration types <code>FIRST</code>
* and <code>LAST</code>.
*
* @throws IllegalStateException
* if no component has yet been added; or
* if delegate is not an instance of <code>PreselectQuery</code>.
* @throws IllegalArgumentException
* if <code>iteration</code> type is <code>FIRST</code> or <code>LAST</code>, but
* <code>sort</code> is <code>null</code>, or if <code>sort</code> represents an
* invalid HQL order by expression.
*/
public void setIterationType(int iteration, String sort)
{
preselectDelegate().setIterationType(iteration, sort);
}
/**
* Add a single sort criterion, in the form of a <code>Resolvable</code>
* object which is resolved at sort time. It is the value of the resolved
* result which is used for the sort.
* <p>
* The sort is ascending, from lowest resolved value to highest.
* <p>
* The delegate must be an instance of <code>PresortDelegate</code>
*
* @param sort
* A resolvable object whose resolved result is used for sorting.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PresortDelegate</code>.
*/
public void addSortCriterion(Resolvable sort)
{
presortDelegate().addSortCriterion(sort);
}
/**
* Add a single sort criterion, in the form of a <code>Resolvable</code>
* object which is resolved at runtime. It is the value of the resolved
* result which is used for the sort.
* <p>
* The delegate must be an instance of <code>PresortDelegate</code>
*
* @param sort
* A resolvable object whose resolved result is used for sorting.
* @param descending
* if <code>true</code>, the sort is descending, from highest
* resolved value to lowest; otherwise, the sort is ascending.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PresortDelegate</code>.
*/
public void addSortCriterion(Resolvable sort, boolean descending)
{
presortDelegate().addSortCriterion(sort, descending);
}
/**
* 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.
*/
@Override
public void setLenientOffEnd(boolean lenientOffEnd)
{
getDelegate().setLenientOffEnd(lenientOffEnd);
}
/**
* Enable all sort criteria set for this query to act as break group
* categories. When the query's results are presorted, the contents of
* each break group are determined.
* <p>
* The delegate must be an instance of <code>PresortDelegate</code>
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PresortDelegate</code>.
*/
public void enableBreakGroups()
{
presortDelegate().enableBreakGroups();
}
/**
* 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)
{
getDelegate().addAccumulator(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
* If <code>true</code>, calls to {@link #iterate()} will not
* cause the accumulator to recalculate immediately, but instead
* to update the accumulator's state such that the next invocation
* of {@link com.goldencode.p2j.util.Accumulator#accumulate()} will
* trigger the actual accumulation update. If <code>false</code>,
* the accumulator recalculates its internal state immediately
*/
public void addAccumulator(Accumulator accum, boolean deferred)
{
getDelegate().addAccumulator(accum, deferred);
}
/**
* Reports if this query (that is, its delegate query) is valid for use.
*
* @return <code>true</code> if this query's delegate is valid for use.
*/
public boolean valid()
{
return valid;
}
/**
* Advance a compound query, triggering one or more of the underlying
* queries to retrieve a new record. This produces a virtual, composite
* row of results which is the combination of the records retrieved by
* each component query.
*
* @throws QueryOffEndException
* if no more records can be retrieved by the underlying queries.
* @throws ErrorConditionException
* if an underlying query triggers an error.
* @throws IllegalStateException
* if delegate is not an instance of <code>CompoundQuery</code>.
*/
public void iterate()
{
compoundDelegate().iterate();
}
/**
* Navigate to the first record which meets the query criteria and retrieve
* it into its record buffer. Use the default substitution parameters and
* lock type.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval or if no record
* could be found when operating in standalone mode.
*/
public boolean first()
{
if (!canGetStmt() || !canGetFirst())
{
return false;
}
advanced = true;
boolean available = false;
available = logical.of(getDelegate().first()).booleanValue();
maybeFireCallback();
return available;
}
/**
* Navigate to the first record which meets the query criteria and retrieve
* it into its record buffer. Use the default substitution parameters, but
* override the default lock type with that provided.
*
* @param lockType
* Lock type to acquire for the retrieved record.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval or if no record
* could be found when operating in standalone mode.
*/
public boolean first(LockType lockType)
{
if (!canGetStmt() || !canGetFirst())
{
return false;
}
advanced = true;
boolean available = logical.of(getDelegate().first(lockType)).booleanValue();
maybeFireCallback();
return available;
}
/**
* Retrieve the first virtual, composite row of results for a compound
* query.
* <p>
* This is a combination of records retrieved by each component query. If
* the compound query involves outer joins, some of the underlying buffers
* may be empty when this method returns.
*
* @param iterating
* <code>true</code> if this method is being invoked within the
* context of an iterating loop, which can only be exited by
* raising an end condition; <code>false</code> if end condition
* should not be raised, even if no further advancement of the
* composite result is possible.
*
* @throws QueryOffEndException
* if no more results were available in iterating mode.
* @throws ErrorConditionException
* if an underlying query triggers an error.
* @throws IllegalStateException
* if delegate is not an instance of <code>CompoundQuery</code>.
*/
public boolean first(boolean iterating)
{
return compoundDelegate().first(iterating);
}
/**
* Retrieve the first virtual, composite row of results for a compound
* query, overriding the lock type to apply to each underlying query.
* <p>
* This is a combination of records retrieved by each component query. If
* the compound query involves outer joins, some of the underlying buffers
* may be empty when this method returns.
*
* @param iterating
* <code>true</code> if this method is being invoked within the
* context of an iterating loop, which can only be exited by
* raising an end condition; <code>false</code> if end condition
* should not be raised, even if no further advancement of the
* composite result is possible.
* @param lockType
* Lock type which should override that of any underlying query.
*
* @throws QueryOffEndException
* if no more results were available in iterating mode.
* @throws ErrorConditionException
* if an underlying query triggers an error.
* @throws IllegalStateException
* if delegate is not an instance of <code>CompoundQuery</code>.
*/
public boolean first(boolean iterating, LockType lockType)
{
return compoundDelegate().first(iterating, lockType);
}
/**
* Navigate to the first record which meets the query criteria and retrieve
* it into its record buffer. Use the default lock type, but override the
* default substitution parameters with those provided.
* <p>
* The delegate must be an instance of <code>RandomAccessQuery</code>
*
* @param values
* Substitution values to use when issuing HQL queries.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval or if no record
* could be found when operating in standalone mode.
* @throws QueryOffEndException
* if no record could be found when operating in compound query
* mode.
* @throws IllegalStateException
* if delegate is not an instance of
* <code>RandomAccessQuery</code>.
*/
public boolean first(Object[] values)
{
return randomAccessDelegate().first(values);
}
/**
* Navigate to the first record which meets the query criteria and retrieve
* it into its record buffer. Override both the default substitution
* parameters, and the default lock type with those provided.
* <p>
* The delegate must be an instance of <code>RandomAccessQuery</code>
*
* @param values
* Substitution values to use when issuing HQL queries.
* @param lockType
* Lock type to acquire for the retrieved record.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval or if no record
* could be found when operating in standalone mode.
* @throws QueryOffEndException
* if no record could be found when operating in compound query
* mode.
* @throws IllegalStateException
* if delegate is not an instance of
* <code>RandomAccessQuery</code>.
*/
public boolean first(Object[] values, LockType lockType)
{
return randomAccessDelegate().first(values, lockType);
}
/**
* Navigate to the last record which meets the query criteria and retrieve
* it into its record buffer. Use the default substitution parameters and
* lock type.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval or if no record
* could be found when operating in standalone mode.
*/
public boolean last()
{
if (!canGetStmt() || !canLastOrPrev())
{
return false;
}
return logical.of(getDelegate().last()).booleanValue();
}
/**
* Navigate to the last record which meets the query criteria and retrieve
* it into its record buffer. Use the default substitution parameters, but
* override the default lock type with that provided.
*
* @param lockType
* Lock type to acquire for the retrieved record.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval or if no record
* could be found when operating in standalone mode.
*/
public boolean last(LockType lockType)
{
if (!canGetStmt() || !canLastOrPrev())
{
return false;
}
boolean avail = logical.of(getDelegate().last(lockType)).booleanValue();
maybeFireCallback();
return avail;
}
/**
* Retrieve the last virtual, composite row of results for a compound
* query.
* <p>
* This is a combination of records retrieved by each component query. If
* the compound query involves outer joins, some of the underlying buffers
* may be empty when this method returns.
*
* @param iterating
* <code>true</code> if this method is being invoked within the
* context of an iterating loop, which can only be exited by
* raising an end condition; <code>false</code> if end condition
* should not be raised, even if no further advancement of the
* composite result is possible.
*
* @throws QueryOffEndException
* if no more results were available in iterating mode.
* @throws ErrorConditionException
* if an underlying query triggers an error.
* @throws IllegalStateException
* if delegate is not an instance of <code>CompoundQuery</code>.
*/
public void last(boolean iterating)
{
compoundDelegate().last(iterating);
}
/**
* Retrieve the last virtual, composite row of results for a compound
* query, overriding the lock type to apply to each underlying query.
* <p>
* This is a combination of records retrieved by each component query. If
* the compound query involves outer joins, some of the underlying buffers
* may be empty when this method returns.
*
* @param iterating
* <code>true</code> if this method is being invoked within the
* context of an iterating loop, which can only be exited by
* raising an end condition; <code>false</code> if end condition
* should not be raised, even if no further advancement of the
* composite result is possible.
* @param lockType
* Lock type which should override that of any underlying query.
*
* @throws QueryOffEndException
* if no more results were available in iterating mode.
* @throws ErrorConditionException
* if an underlying query triggers an error.
* @throws IllegalStateException
* if delegate is not an instance of <code>CompoundQuery</code>.
*/
public void last(boolean iterating, LockType lockType)
{
compoundDelegate().last(iterating, lockType);
}
/**
* Navigate to the last record which meets the query criteria and retrieve
* it into its record buffer. Use the default lock type, but override the
* default substitution parameters with those provided.
* <p>
* The delegate must be an instance of <code>RandomAccessQuery</code>
*
* @param values
* Substitution values to use when issuing HQL queries.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval or if no record
* could be found when operating in standalone mode.
* @throws QueryOffEndException
* if no record could be found when operating in compound query
* mode.
* @throws IllegalStateException
* if delegate is not an instance of
* <code>RandomAccessQuery</code>.
*/
public void last(Object[] values)
{
randomAccessDelegate().last(values);
}
/**
* Navigate to the last record which meets the query criteria and retrieve
* it into its record buffer. Override both the default substitution
* parameters, and the default lock type with those provided.
* <p>
* The delegate must be an instance of <code>RandomAccessQuery</code>
*
* @param values
* Substitution values to use when issuing HQL queries.
* @param lockType
* Lock type to acquire for the retrieved record.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval or if no record
* could be found when operating in standalone mode.
* @throws QueryOffEndException
* if no record could be found when operating in compound query
* mode.
* @throws IllegalStateException
* if delegate is not an instance of
* <code>RandomAccessQuery</code>.
*/
public void last(Object[] values, LockType lockType)
{
randomAccessDelegate().last(values, lockType);
}
/**
* Navigate to the next record which meets the query criteria and retrieve
* it into its record buffer. Use the default substitution parameters and
* lock type.
* <p>
* Use the record most recently loaded into the backing buffer as the
* reference point when determining the next record to visit. If no
* record has yet been loaded into the buffer, retrieve the first record
* which meets the query criteria.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval.
*/
public boolean next()
{
if (!canGetStmt())
{
return false;
}
advanced = true;
boolean hasNext = getDelegate().next();
maybeFireCallback();
return hasNext;
}
/**
* Navigate to the next record which meets the query criteria and retrieve
* it into its record buffer. Use the default substitution parameters, but
* override the default lock type with that provided.
* <p>
* Use the record most recently loaded into the backing buffer as the
* reference point when determining the next record to visit. If no
* record has yet been loaded into the buffer, retrieve the first record
* which meets the query criteria.
*
* @param lockType
* Lock type to acquire for the retrieved record.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval.
*/
public boolean next(LockType lockType)
{
if (!canGetStmt())
{
return false;
}
advanced = true;
boolean hasNext = getDelegate().next(lockType);
maybeFireCallback();
return hasNext;
}
/**
* Retrieve the next virtual, composite row of results for a compound
* query.
* <p>
* This is a combination of records retrieved by each component query. If
* the compound query involves outer joins, some of the underlying buffers
* may be empty when this method returns.
*
* @param iterating
* <code>true</code> if this method is being invoked within the
* context of an iterating loop, which can only be exited by
* raising an end condition; <code>false</code> if end condition
* should not be raised, even if no further advancement of the
* composite result is possible.
*
* @throws QueryOffEndException
* if no more results were available in iterating mode.
* @throws ErrorConditionException
* if an underlying query triggers an error.
* @throws IllegalStateException
* if delegate is not an instance of <code>CompoundQuery</code>.
*/
public boolean next(boolean iterating)
{
return compoundDelegate().next(iterating);
}
/**
* Retrieve the next virtual, composite row of results for a compound
* query, overriding the lock type to apply to each underlying query.
* <p>
* This is a combination of records retrieved by each component query. If
* the compound query involves outer joins, some of the underlying buffers
* may be empty when this method returns.
*
* @param iterating
* <code>true</code> if this method is being invoked within the
* context of an iterating loop, which can only be exited by
* raising an end condition; <code>false</code> if end condition
* should not be raised, even if no further advancement of the
* composite result is possible.
* @param lockType
* Lock type which should override that of any underlying query.
*
* @throws QueryOffEndException
* if no more results were available in iterating mode.
* @throws ErrorConditionException
* if an underlying query triggers an error.
* @throws IllegalStateException
* if delegate is not an instance of <code>CompoundQuery</code>.
*/
public boolean next(boolean iterating, LockType lockType)
{
return compoundDelegate().next(iterating, lockType);
}
/**
* Navigate to the next record which meets the query criteria and retrieve
* it into its record buffer. Use the default lock type, but override the
* default substitution parameters with those provided.
* <p>
* Use the record most recently loaded into the backing buffer as the
* reference point when determining the next record to visit. If no
* record has yet been loaded into the buffer, retrieve the first record
* which meets the query criteria.
* <p>
* The delegate must be an instance of <code>RandomAccessQuery</code>
*
* @param values
* Substitution values to use when issuing HQL queries.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval.
* @throws IllegalStateException
* if delegate is not an instance of
* <code>RandomAccessQuery</code>.
*/
public boolean next(Object[] values)
{
return randomAccessDelegate().next(values);
}
/**
* Navigate to the next record which meets the query criteria and retrieve
* it into its record buffer. Override both the default substitution
* parameters, and the default lock type with those provided.
* <p>
* Use the record most recently loaded into the backing buffer as the
* reference point when determining the next record to visit. If no
* record has yet been loaded into the buffer, retrieve the first record
* which meets the query criteria.
* <p>
* The delegate must be an instance of <code>RandomAccessQuery</code>
*
* @param values
* Substitution values to use when issuing HQL queries.
* @param lockType
* Lock type to acquire for the retrieved record.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval.
* @throws IllegalStateException
* if delegate is not an instance of
* <code>RandomAccessQuery</code>.
*/
public boolean next(Object[] values, LockType lockType)
{
return randomAccessDelegate().next(values, lockType);
}
/**
* Navigate to the previous record which meets the query criteria and
* retrieve it into its record buffer. Use the default substitution
* parameters and lock type.
* <p>
* Use the record most recently loaded into the backing buffer as the
* reference point when determining the previous record to visit. If no
* record has yet been loaded into the buffer, retrieve the last record
* which meets the query criteria.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval.
*/
public boolean previous()
{
if (!canGetStmt() || !canLastOrPrev())
{
return false;
}
boolean avail = getDelegate().previous();
maybeFireCallback();
return avail;
}
/**
* Navigate to the previous record which meets the query criteria and
* retrieve it into its record buffer. Use the default substitution
* parameters, but override the default lock type with that provided.
* <p>
* Use the record most recently loaded into the backing buffer as the
* reference point when determining the previous record to visit. If no
* record has yet been loaded into the buffer, retrieve the last record
* which meets the query criteria.
*
* @param lockType
* Lock type to acquire for the retrieved record.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval.
*/
public boolean previous(LockType lockType)
{
if (!canGetStmt() || !canLastOrPrev())
{
return false;
}
boolean avail = getDelegate().previous(lockType);
maybeFireCallback();
return avail;
}
/**
* Retrieve the previous virtual, composite row of results for a compound
* query.
* <p>
* This is a combination of records retrieved by each component query. If
* the compound query involves outer joins, some of the underlying buffers
* may be empty when this method returns.
*
* @param iterating
* <code>true</code> if this method is being invoked within the
* context of an iterating loop, which can only be exited by
* raising an end condition; <code>false</code> if end condition
* should not be raised, even if no further advancement of the
* composite result is possible.
*
* @throws QueryOffEndException
* if no more results were available in iterating mode.
* @throws ErrorConditionException
* if an underlying query triggers an error.
* @throws IllegalStateException
* if delegate is not an instance of <code>CompoundQuery</code>.
*/
public boolean previous(boolean iterating)
{
return compoundDelegate().previous(iterating);
}
/**
* Retrieve the previous virtual, composite row of results for a compound
* query, overriding the lock type to apply to each underlying query.
* <p>
* This is a combination of records retrieved by each component query. If
* the compound query involves outer joins, some of the underlying buffers
* may be empty when this method returns.
*
* @param iterating
* <code>true</code> if this method is being invoked within the
* context of an iterating loop, which can only be exited by
* raising an end condition; <code>false</code> if end condition
* should not be raised, even if no further advancement of the
* composite result is possible.
* @param lockType
* Lock type which should override that of any underlying query.
*
* @throws QueryOffEndException
* if no more results were available in iterating mode.
* @throws ErrorConditionException
* if an underlying query triggers an error.
* @throws IllegalStateException
* if delegate is not an instance of <code>CompoundQuery</code>.
*/
public boolean previous(boolean iterating, LockType lockType)
{
return compoundDelegate().previous(iterating, lockType);
}
/**
* Navigate to the previous record which meets the query criteria and
* retrieve it into its record buffer. Use the default lock type, but
* override the default substitution parameters with those provided.
* <p>
* Use the record most recently loaded into the backing buffer as the
* reference point when determining the previous record to visit. If no
* record has yet been loaded into the buffer, retrieve the last record
* which meets the query criteria.
* <p>
* The delegate must be an instance of <code>RandomAccessQuery</code>
*
* @param values
* Substitution values to use when issuing HQL queries.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval.
* @throws IllegalStateException
* if delegate is not an instance of
* <code>RandomAccessQuery</code>.
*/
public boolean previous(Object[] values)
{
return randomAccessDelegate().previous(values);
}
/**
* Navigate to the previous record which meets the query criteria and
* retrieve it into its record buffer. Override both the default
* substitution parameters, and the default lock type with those provided.
* <p>
* Use the record most recently loaded into the backing buffer as the
* reference point when determining the previous record to visit. If no
* record has yet been loaded into the buffer, retrieve the last record
* which meets the query criteria.
* <p>
* The delegate must be an instance of <code>RandomAccessQuery</code>
*
* @param values
* Substitution values to use when issuing HQL queries.
* @param lockType
* Lock type to acquire for the retrieved record.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval.
* @throws IllegalStateException
* if delegate is not an instance of
* <code>RandomAccessQuery</code>.
*/
public boolean previous(Object[] values, LockType lockType)
{
return randomAccessDelegate().previous(values, lockType);
}
/**
* Reload the record most recently loaded into the backing record buffer,
* if any. Use the default lock type.
*
* @throws ErrorConditionException
* if an error occurred during record reload.
*/
public boolean current()
{
if (!canGetStmt())
{
return false;
}
boolean available = getDelegate().current();
maybeFireCallback();
return available;
}
/**
* Reload the record most recently loaded into the backing record buffer,
* if any. Override the default lock type.
*
* @param lockType
* New lock type to apply to the record.
*
* @throws ErrorConditionException
* if an error occurred during record reload, or the lock could
* not be transitioned to the requested type.
*/
public boolean current(LockType lockType)
{
if (!canGetStmt())
{
return false;
}
boolean available = getDelegate().current(lockType);
maybeFireCallback();
return available;
}
/**
* Navigate to a particular record which meets the query criteria and
* retrieve it into its record buffer. No more than one record may match
* the criteria. Use the default substitution parameters and lock type.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval or if more than
* one record is found which match the criteria.
* @throws QueryOffEndException
* if no record could be found when operating in compound query
* mode.
*/
public boolean unique()
{
boolean avail = getDelegate().unique();
maybeFireCallback();
return avail;
}
/**
* Navigate to a particular record which meets the query criteria and
* retrieve it into its record buffer. No more than one record may match
* the criteria. Use the default substitution parameters, but override
* the default lock type with that provided.
*
* @param lockType
* Lock type to acquire for the retrieved record.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval or if more than
* one record is found which match the criteria.
* @throws QueryOffEndException
* if no record could be found when operating in compound query
* mode.
*/
public boolean unique(LockType lockType)
{
boolean avail = getDelegate().unique(lockType);
maybeFireCallback();
return avail;
}
/**
* Navigate to a particular record which meets the query criteria and
* retrieve it into its record buffer. No more than one record may match
* the criteria. Use the default lock type, but override the default
* substitution parameters with those provided.
* <p>
* The delegate must be an instance of <code>RandomAccessQuery</code>
*
* @param values
* Substitution values to use when issuing HQL queries.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval or if more than
* one record is found which match the criteria.
* @throws QueryOffEndException
* if no record could be found when operating in compound query
* mode.
* @throws IllegalStateException
* if delegate is not an instance of
* <code>RandomAccessQuery</code>.
*/
public boolean unique(Object[] values)
{
return randomAccessDelegate().unique(values);
}
/**
* Navigate to a particular record which meets the query criteria and
* retrieve it into its record buffer. No more than one record may match
* the criteria. Override both the default substitution parameters, and
* the default lock type with those provided.
* <p>
* The delegate must be an instance of <code>RandomAccessQuery</code>
*
* @param values
* Substitution values to use when issuing HQL queries.
* @param lockType
* Lock type to acquire for the retrieved record.
*
* @throws ErrorConditionException
* if an error occurred during record retrieval or if more than
* one record is found which match the criteria.
* @throws QueryOffEndException
* if no record could be found when operating in compound query
* mode.
* @throws IllegalStateException
* if delegate is not an instance of
* <code>RandomAccessQuery</code>.
*/
public boolean unique(Object[] values, LockType lockType)
{
return randomAccessDelegate().unique(values, 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasAny()
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasAny(Object[] values)
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasAny(LockType lockType)
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasAny(Object[] values, LockType lockType)
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasOne()
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasOne(Object[] values)
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasOne(LockType lockType)
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasOne(Object[] values, LockType lockType)
{
throw new UnsupportedOperationException();
}
/**
* 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()
{
return fetchOnReposition;
}
/**
* 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)
{
fetchOnReposition = enable;
if (delegate != null)
{
getDelegate().setFetchOnReposition(enable);
}
}
/**
* 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 listener
* The listener to be notified.
*/
@Override
public void addQueryEventListener(QueryEventListener listener)
{
// for the moment the QueryOpen notification only handles dynamic queries. The wrapper does
// not notify about the event BUT will propagate the event to its [delegate] if any, and
// that query will notify its listeners.
if (delegate != null)
{
getDelegate().addQueryEventListener(listener);
}
}
/**
* Register a listener to receive notifications about the query has been opened.
*
* @param listener
* The listener to be notified.
*/
public void addOpenedListener(QueryOpenedListener listener)
{
openedListeners.add(listener);
}
/**
* De-register a listener to receive notifications about the query has been opened.
*
* @param listener
* The listener to be removed.
*/
public void removeOpenedListener(QueryOpenedListener listener)
{
openedListeners.remove(listener);
}
/**
* Register a listener to receive notifications reposition events for this
* query.
*
* @param listener
* Reposition listener to be registered.
*/
public void addRepositionListener(RepositionListener listener)
{
repoListeners.add(listener);
if (delegate != null)
{
getDelegate().addRepositionListener(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)
{
repoListeners.remove(listener);
if (delegate != null)
{
getDelegate().removeRepositionListener(listener);
}
}
/**
* Sets an external result list handler and marks the query as browsed.
*
* @param resultListHandler
* External result list handler.
*/
public void setBrowsed(ResultListHandler resultListHandler)
{
this.externalResultListHandler = resultListHandler;
setBrowsed(resultListHandler != null);
}
/**
* 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)
{
this.browsed = browsed;
if (!browsed)
{
externalResultListHandler = null;
}
if (delegate != null)
{
getDelegate().setBrowsed(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()
{
return browsed;
}
/**
* 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)
{
if (!canReposition())
{
return;
}
getDelegate().repositionByID(id);
maybeFireCallback();
}
/**
* 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.
*
* If an array element is unknown, this element and all subsequent elements
* are ignored.
*
* @throws ErrorConditionException
* if this query is not a scrolling query;
* if any of the specified IDs represents the unknown value.
*/
public void repositionByID(rowid id1, rowid... joinIDs)
{
if (!canReposition())
{
return;
}
for(int i = 0; i < joinIDs.length; i++)
{
if(joinIDs[i].isUnknown())
{
rowid[] newIds = new rowid[i];
System.arraycopy(joinIDs, 0, newIds, 0, i);
joinIDs = newIds;
break;
}
}
getDelegate().repositionByID(id1, joinIDs);
maybeFireCallback();
}
/**
* 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.
*/
@Override
public boolean repositionByID(Long... joinIDs)
{
boolean ret = getDelegate().repositionByID(joinIDs);
maybeFireCallback();
return ret;
}
/**
* 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 this query is not a scrolling query;
* if <code>row</code> represents unknown value.
*/
public void reposition(NumberType row)
{
if (!canReposition())
{
return;
}
getDelegate().reposition(row);
maybeFireCallback();
}
/**
* 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.
*
* @throws ErrorConditionException
* if this query is not a scrolling query.
*/
public void reposition(int row)
{
/*
WARNING: this is used internally, do not validate here
if (!canReposition())
{
return;
}
*/
getDelegate().reposition(row);
maybeFireCallback();
}
/**
* 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 this query is not a scrolling query;
* if <code>rows</code> represents the unknown value.
*/
public boolean forward(NumberType rows)
{
if (!canReposition())
{
return false;
}
boolean ret = getDelegate().forward(rows);
maybeFireCallback();
return ret;
}
/**
* 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 this query is not a scrolling query.
*/
public boolean forward(int rows)
{
if (!canReposition())
{
return false;
}
boolean ret = getDelegate().forward(rows);
maybeFireCallback();
return ret;
}
/**
* 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 this query is not a scrolling query;
* if <code>rows</code> represents the unknown value.
*/
public boolean backward(NumberType rows)
{
if (!canReposition())
{
return false;
}
boolean ret = getDelegate().backward(rows);
maybeFireCallback();
return ret;
}
/**
* 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 this query is not a scrolling query.
*/
public boolean backward(int rows)
{
if (!canReposition())
{
return false;
}
boolean ret = getDelegate().backward(rows);
maybeFireCallback();
return ret;
}
/**
* Get the <b><i>current</i></b> size of the cached results list. However,
* since this cache is 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.
*
* @throws ErrorConditionException
* if this query is not a scrolling query.
*/
public integer size()
{
return getDelegate().size();
}
/**
* Get the recursive DATA-RELATION the query is to FILL for.
* @return the recursive DATA-RELATION the query is to FILL for
*/
@Override
public DataRelation getDataRelation()
{
return this.relation;
}
/**
* Set the recursive DATA-RELATION the query is to FILL for.
* @param relation
* the recursive DATA-RELATION the query is to FILL for
*/
@Override
public void setDataRelation(final DataRelation relation)
{
this.relation = relation;
if (this.delegate != null && relation == null)
{
this.delegate.setDataRelation(relation);
}
}
/**
* 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 the current row in the query
* result set.
*/
public integer currentRow()
{
return getDelegate().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.
*
* @throws ErrorConditionException
* if this query is not a scrolling query.
*/
public integer currentRowImpl()
{
return getDelegate().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.
*
* @throws ErrorConditionException
* if this query is not a scrolling query.
*/
public logical isOffEnd()
{
return closed ? logical.UNKNOWN : getDelegate().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.
*
* @throws ErrorConditionException
* if this query is not a scrolling query.
*/
public boolean _isOffEnd()
{
return getDelegate()._isOffEnd();
}
/**
* Get the off-end status of the 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()
{
return getDelegate().getOffEnd();
}
/**
* Determine whether the query result row currently being visited is the
* first row in the presorted results list.
* <p>
* The delegate must be an instance of <code>PresortDelegate</code>
*
* @return <code>true</code> if the current result row is the first row,
* else <code>false</code>.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PresortDelegate</code>.
*/
public logical isFirst()
{
return presortDelegate().isFirst();
}
/**
* Determine whether the query result row currently being visited is the
* first row within a break group whose category is identified by the
* specified resolvable object.
* <p>
* The delegate must be an instance of <code>PresortDelegate</code>
*
* @param key
* Break group category key. Must be the same object reference
* as was specified previously when invoking one of the
* <code>addSortCriterion</code> method variants.
*
* @return <code>true</code> if current row is first in a break group;
* <code>false</code> if it is not; unknown value if break groups
* have not been enabled.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PresortDelegate</code>.
*/
public logical isFirstOfGroup(Resolvable key)
{
return presortDelegate().isFirstOfGroup(key);
}
/**
* 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}.
*/
public logical isFirstOfGroup(integer level)
{
return presortDelegate().isFirstOfGroup(level);
}
/**
* 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}.
*/
public logical isFirstOfGroup(int level)
{
return isFirstOfGroup(new integer(level));
}
/**
* Determine whether the query result row currently being visited is the
* last row in the presorted results list.
* <p>
* The delegate must be an instance of <code>PresortDelegate</code>
*
* @return <code>true</code> if the current result row is the last row,
* else <code>false</code>.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PresortDelegate</code>.
*/
public logical isLast()
{
return presortDelegate().isLast();
}
/**
* Determine whether the query result row currently being visited is the
* first row within a break group whose category is identified by the
* specified resolvable object.
* <p>
* The delegate must be an instance of <code>PresortDelegate</code>
*
* @param key
* Break group category key. Must be the same object reference
* as was specified previously when invoking one of the
* <code>addSortCriterion</code> method variants.
*
* @return <code>true</code> if current row is first in a break group;
* <code>false</code> if it is not; unknown value if break groups
* have not been enabled.
*
* @throws IllegalStateException
* if delegate is not an instance of <code>PresortDelegate</code>.
*/
public logical isLastOfGroup(Resolvable key)
{
return presortDelegate().isLastOfGroup(key);
}
/**
* 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}.
*/
public logical isLastOfGroup(integer level)
{
return presortDelegate().isLastOfGroup(level);
}
/**
* 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}.
*/
public logical isLastOfGroup(int level)
{
return isLastOfGroup(new integer(level));
}
/**
* 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()
{
return getDelegate().isPreselect();
}
/**
* Indicate whether this query is a preselect query by its nature.
*
* @return <code>true</code>.
*/
public boolean isNativelyPreselect()
{
return getDelegate().isNativelyPreselect();
}
/**
* 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)
{
delegate.notifyRepositionListeners(closed, error, targetRepositionRow);
}
/**
* Notify all registered listeners that query is repositioned in case if
* query is attached to browse widget.
*
* @deprecated Use #open() instead.
*/
@Deprecated
public void notifyListeners()
{
open();
}
/**
* Indicate whether this query stands alone, or is the component of
* another query, or is wrapped by a query wrapper.
*
* @return <code>true</code>; query wrappers may not themselves be
* wrapped.
*/
public boolean isStandalone()
{
return true;
}
/**
* 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.
* <p>
* Instances of <code>QueryWrapper</code> may not be wrapped in other
* queries or query wrappers, so this implementation throws an exception
* if this method is invoked with a parameter of <code>true</code>.
*
* @param standalone
* <code>true</code> to set query as standalone;
* <code>false</code> to set query as contained.
*
* @throws UnsupportedOperationException
* if <code>standalone</code> is set to <code>true</code>.
*/
public void setStandalone(boolean standalone)
{
if (!standalone)
{
throw new UnsupportedOperationException(
"Query wrapper must be standalone");
}
}
/**
* Delegate cleanup processing to the query wrapped by this object.
*
* @see P2JQuery#cleanup()
*/
public void cleanup()
{
if (!closed)
{
delegate.cleanup();
}
}
/**
* Generate a handle to the query object.
*
* Returns a handle of a query object.
*
* @return query handle
*/
public handle asHandle()
{
return new handle(this);
}
/**
* Conversion of GET-BUFFER-HANDLE() method (KW_GET_BUFH).
*
* Returns a handle of the first buffer of a query object.
*
* @return buffer handle
*/
public handle bufferHandle()
{
return bufferHandle(1);
}
/**
* Conversion of GET-BUFFER-HANDLE() method (KW_GET_BUFH).
*
* Returns a handle of the first buffer of a query object.
*
* @return buffer handle
*/
public Buffer bufferHandleNative()
{
return getBufferByIndex(1);
}
/**
* Conversion of GET-BUFFER-HANDLE() method (KW_GET_BUFH).
*
* Returns a handle of a particular buffer of a query object.
*
* @param bufferName
* buffer-name. A CHARACTER expression that evaluates to the name
* of a buffer in the query or DataSet object.
*
* @return buffer handle
*/
public handle bufferHandle(String bufferName)
{
return bufferHandle(new character(bufferName));
}
/**
* Conversion of GET-BUFFER-HANDLE() method (KW_GET_BUFH).
*
* Returns a handle of a particular buffer of a query object.
*
* @param bufferName
* buffer-name. A CHARACTER expression that evaluates to the name
* of a buffer in the query or DataSet object.
*
* @return buffer handle
*/
public handle bufferHandle(character bufferName)
{
for (int i = 0; i < buffers.size(); i++)
{
Buffer buf = buffers.get(i);
if (CompareOps._isEqual(bufferName, buf.name()))
{
handle h = new handle();
h.assign(buf);
return h;
}
}
String errMsg = "Query method argument must be the name of a query buffer or an integer " +
"from 1 to %d for query %s";
errMsg = String.format(errMsg, numBuffers().intValue(), qname);
ErrorManager.recordOrShowDatabaseError(7361, errMsg, false, false);
return new handle();
}
/**
* Conversion of GET-BUFFER-HANDLE() method (KW_GET_BUFH).
*
* Returns a handle of a particular buffer of a query object.
*
* @param bufferSequenceNumber
* buffer-sequence-number. An INTEGER that represents the sequence
* number of the desired buffer.
*
* @return buffer handle
*/
public handle bufferHandle(int bufferSequenceNumber)
{
return bufferHandle(new integer(bufferSequenceNumber));
}
/**
* Conversion of GET-BUFFER-HANDLE() method (KW_GET_BUFH).
*
* Returns a handle of a particular buffer of a query object.
*
* @param bufferSequenceNumber
* buffer-sequence-number. An INTEGER that represents the sequence
* number of the desired buffer.
*
* @return buffer handle
*/
@Override
public handle bufferHandle(int64 bufferSequenceNumber)
{
int idx = bufferSequenceNumber.isUnknown() ? 0 : bufferSequenceNumber.intValue();
return new handle(getBufferByIndex(idx));
}
/**
* Conversion of GET-BUFFER-HANDLE() method (KW_GET_BUFH).
*
* Returns a particular buffer of a query object.
*
* @param bufferSequenceNumber
* buffer-sequence-number. An INTEGER that represents the sequence
* number of the desired buffer.
*
* @return buffer object
*/
public Buffer getBufferByIndex(int bufferSequenceNumber)
{
if (bufferSequenceNumber >= 1 && bufferSequenceNumber <= buffers.size())
{
return buffers.get(bufferSequenceNumber - 1);
}
String errMsg = "Query method argument must be the name of a query buffer or an integer " +
"from 1 to %d for query %s";
errMsg = String.format(errMsg, numBuffers().intValue(), qname);
ErrorManager.recordOrShowDatabaseError(7361, errMsg, false, false);
return null;
}
/**
* Conversion of QUERY-CLOSE() method (KW_QRY_CLOS).
*
* Closes a query object.
*
* @return <code>true</code> if QUERY-CLOSE() succeeds,
* else <code>false</code>.
*/
public logical queryClose()
{
boolean success = true;
if (delegate != null)
{
delegate.notifyQueryCloseListeners();
}
try
{
close();
}
catch (ErrorConditionException exc)
{
success = false;
}
return logical.of(success);
}
/**
* 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>.
*/
public logical queryBackward(int rows)
{
return queryBackward(new integer(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} 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 logical queryBackward(NumberType rows)
{
if (rows.isUnknown())
{
// TODO: what error should be shown?
return logical.of(false);
}
try
{
return logical.of(backward(rows));
}
catch (ErrorConditionException exc)
{
return logical.of(false);
}
}
/**
* 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>.
*/
public logical queryForward(int rows)
{
return queryForward(new integer(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} 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 logical queryForward(NumberType rows)
{
if (rows.isUnknown())
{
// TODO: what error should be shown?
return logical.of(false);
}
try
{
return logical.of(forward(rows));
}
catch (ErrorConditionException exc)
{
return logical.of(false);
}
}
/**
* 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>.
*/
public logical queryReposition(int n)
{
return queryReposition(new integer(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>.
*/
public logical queryReposition(NumberType n)
{
boolean success = true;
try
{
reposition(n);
}
catch (ErrorConditionException exc)
{
success = false;
}
return logical.of(success);
}
/**
* 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>.
*/
public logical queryRepositionByID(rowid id1, rowid...joinIDs)
{
boolean success = true;
try
{
repositionByID(id1, joinIDs);
}
catch (ErrorConditionException exc)
{
success = false;
}
return logical.of(success);
}
/**
* 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>.
*/
@Override
public logical queryRepositionByID(rowid[] joinIDs)
{
if (joinIDs.length == 1)
{
return queryRepositionByID(joinIDs[0]);
}
else if (joinIDs.length == 0)
{
return logical.FALSE;
}
else
{
rowid[] r = new rowid[joinIDs.length - 1];
System.arraycopy(joinIDs, 1, r, 0, r.length);
return queryRepositionByID(joinIDs[0], r);
}
}
/**
* 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>.
*/
public logical queryRepositionByID(character rowId)
{
UnimplementedFeature.missing("QUERY:REPOSITION-BY-ID(character)");
return logical.UNKNOWN;
}
/**
* Conversion of NUM-RESULTS attribute (KW_NUM_RES).
*
* Getter of NUM-RESULTS attribute
*
* @return Number of rows currently in the results list of a scrolling query. If the query
* is not open or it is not scrolling, returns the unknown value.
*/
public integer getNumResults()
{
P2JQuery delegate = getDelegate();
if (!delegate.isScrolling() || (prepareString != null && closed))
{
return new integer();
}
try
{
return delegate.size();
}
catch (UnsupportedOperationException e)
{
return new integer();
}
}
/**
* Adds one new buffer to a query object or dynamic DataSet object,
* without affecting the other buffers, if any. Use the SET-BUFFERS( )
* method to remove all prior buffers and set all buffers for the object
* at the same time.
*
* @param bufHandle
* A buffer handle to add.
*
* @return true on success
*/
public logical addBuffer(handle bufHandle)
{
if (!canAddBuffer() || !validBuffer(bufHandle, 1))
{
return logical.of(false);
}
if (!closed)
{
close();
}
Buffer buf = (Buffer) bufHandle.get();
return addBuffer(buf);
}
/**
* Adds one new buffer to a query object or dynamic DataSet object,
* without affecting the other buffers, if any. Use the SET-BUFFERS( )
* method to remove all prior buffers and set all buffers for the object
* at the same time.
*
* @param buf
* A buffer to add.
*
* @return true on success
*/
@Override
public logical addBuffer(Buffer buf)
{
return addBuffer(buf, false);
}
/**
* Adds one new buffer to a query object or dynamic DataSet object,
* without affecting the other buffers, if any. Use the SET-BUFFERS( )
* method to remove all prior buffers and set all buffers for the object
* at the same time.
*
* @param bufName
* A buffer name use to identify a buffer to be added.
*
* @return true on success
*/
@Override
public logical addBuffer(character bufName)
{
return addBuffer(bufName.toStringMessage());
}
/**
* Adds one new buffer to a query object or dynamic DataSet object,
* without affecting the other buffers, if any. Use the SET-BUFFERS( )
* method to remove all prior buffers and set all buffers for the object
* at the same time.
*
* @param bufName
* A buffer name use to identify a buffer to be added.
*
* @return true on success
*/
@Override
public logical addBuffer(String bufName)
{
if (!canAddBuffer())
{
return logical.of(false);
}
Buffer crtBuff = parseBuffer(BufferManager.get(), bufName, 1);
if (crtBuff == null)
{
return logical.of(false);
}
return addBuffer(crtBuff);
}
/**
* Adds one new buffer to a query object or dynamic DataSet object,
* without affecting the other buffers, if any. Use the SET-BUFFERS( )
* method to remove all prior buffers and set all buffers for the object
* at the same time.
*
* @param buf
* A buffer to add.
* @param staticCall
* <code>true</code> if it is internal call for a static query.
*
* @return true on success
*/
public logical addBuffer(Buffer buf, boolean staticCall)
{
if (!staticCall)
{
if (!canAddBuffer())
{
return logical.of(false);
}
if (!closed)
{
close();
}
// reset the prepare-string
prepareString = null;
}
else if (!dynamic && !cleanerRegistered)
{
registerCleaner();
}
// if the buffer already exists, is added anyway
this.buffers.add(((BufferImpl) buf).ref());
((BufferImpl) buf).setQuery(this);
RecordBuffer recordBuffer = ((BufferImpl) buf).buffer();
recordBuffer.registerRelatedQuery(this);
return logical.of(true);
}
/**
* Sets buffers for the query. Any buffers previously added
* or set are removed. Use the <code>addBuffer()</code> method to add one
* buffer to the object, without affecting the other buffers, if any.
* This method is the equivalent of <code>SET-BUFFERS()</code> method
* from 4GL.
*
* @param hBuffers
* Variable argument list of buffer handles to be set.
* In 4GL, the maximum number of buffers per query is 18.
*
* @return true on success
*/
@Override
public logical setBuffers(handle... hBuffers)
{
if (!canAddBuffer())
{
return logical.of(false);
}
// validate all handles upfront
for (int i = 0; i < hBuffers.length; i++)
{
if (!validBuffer(hBuffers[i], i + 1))
{
return logical.of(false);
}
}
if (!closed)
{
close();
}
resetQuery();
for (handle h : hBuffers)
{
addBuffer((Buffer) h.get());
}
return logical.of(true);
}
/**
* Sets buffers for the query. Any buffers previously added
* or set are removed. Use the <code>addBuffer()</code> method to add one
* buffer to the object, without affecting the other buffers, if any.
* This method is the equivalent of <code>SET-BUFFERS()</code> method
* from 4GL.
*
* @param bufs
* Variable argument list of Buffer to be set.
* In 4GL, the maximum number of buffers per query is 18.
*
* @return true on success
*/
@Override
public logical setBuffers(Buffer... bufs)
{
if (!canAddBuffer())
{
return logical.of(false);
}
if (!closed)
{
close();
}
resetQuery();
for (Buffer buf : bufs)
{
addBuffer(buf);
}
return logical.of(true);
}
/**
* Sets buffers for the query. Any buffers previously added
* or set are removed. Use the <code>addBuffer()</code> method to add one
* buffer to the object, without affecting the other buffers, if any.
* This method is the equivalent of <code>SET-BUFFERS()</code> method
* from 4GL.
*
* @param bufs
* Variable argument list of Buffer to be set.
* In 4GL, the maximum number of buffers per query is 18.
*
* @return true on success
*/
@Override
public logical setBuffers(Object... bufs)
{
if (!canAddBuffer())
{
return logical.of(false);
}
if (!closed)
{
close();
}
resetQuery();
BufferManager bm = null;
ArrayList<Buffer> localBuffers = new ArrayList<>(bufs.length);
for (int i = 0; i < bufs.length; i++)
{
Buffer crtBuff = null;
if (bufs[i] instanceof Buffer)
{
crtBuff = (Buffer) bufs[i];
}
else if (bufs[i] instanceof handle)
{
handle asHandle = (handle) bufs[i];
// references must be valid:
if (asHandle.isUnknown() || !asHandle.isType(LegacyResource.BUFFER))
{
ErrorManager.recordOrShowError(7319, Integer.toString(i + 1));
// ADD/SET-BUFFERS argument <argnumber> was invalid or not found.
return logical.of(false);
}
crtBuff = (Buffer) asHandle.get();
}
else if (bufs[i] instanceof character || bufs[i] instanceof String)
{
if (bm == null)
{
bm = BufferManager.get();
}
String name = (bufs[i] instanceof String)
? (String) bufs[i] : ((character) bufs[i]).toStringMessage();
crtBuff = parseBuffer(bm, name, i + 1);
if (crtBuff == null)
{
return logical.of(false);
}
}
else
{
// unknown/invalid data type
ErrorManager.recordOrShowError(7319, Integer.toString(i + 1));
// ADD/SET-BUFFERS argument <arg-number> was invalid or not found.
return logical.of(false);
}
localBuffers.add(crtBuff);
}
for (int i = 0; i < localBuffers.size(); i++)
{
Buffer buffer = localBuffers.get(i);
addBuffer(buffer);
}
return logical.of(true);
}
/**
* Compiles a predicate (query condition). The query must be open after this call.
* This method is the equivalent of {@code QUERY-PREPARE()} method from 4GL.
*
* @param predicate
* The predicate to be prepared by this query. The syntax of the string is the same
* of the {@code OPEN QUERY} statement of the 4GL.
*
* @return true on success
*/
@Override
public logical prepare(String predicate)
{
return prepare(new character(predicate));
}
/**
* Compiles a predicate (query condition). The query must be open after this call.
* This method is the equivalent of <code>QUERY-PREPARE()</code> method from 4GL.
*
* @param predicate
* The predicate to be prepared by this query. The syntax of the string is the same
* of the <code>OPEN QUERY</code> statement of the 4GL.
*
* @return true on success
*/
@Override
public logical prepare(character predicate)
{
// validate first
if (predicate.isUnknown())
{
final String errMsg =
"QUERY-PREPARE requires a valid non-null character argument for query %s";
ErrorManager.recordOrShowDatabaseError(7321, String.format(errMsg, qname), false, false);
return logical.of(false);
}
if (buffers.isEmpty())
{
final String errMsg =
"QUERY-PREPARE requires that SET-BUFFERS has been used to assign buffers to query %s";
ErrorManager.recordOrShowDatabaseError(7322, String.format(errMsg, qname), false, false);
return logical.of(false);
}
// close the query, if opened
close();
// reset vars
prepareString = null;
dynamicDelegate = false;
// parse the predicate and instantiate a new delegate
String qprepare = predicate.toStringMessage();
P2JQuery query = DynamicQueryHelper.parseQuery(buffers, qprepare, qname, substBuffers);
if (query != null)
{
this.dynamicDelegate = true;
this.prepareString = qprepare;
query.setDynamicPredicate(true);
assignImpl(query, false);
}
return logical.of(query != null);
}
/**
* 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
*/
@Override
public logical queryOpen()
{
String errMsg = "QUERY-OPEN for query %s requires a previous QUERY-PREPARE";
if (prepareString == null)
{
ErrorManager.recordOrShowDatabaseError(7312, String.format(errMsg, qname), true, false);
return logical.of(false);
}
if (!closed)
{
close();
}
// call onOpen() if needed.
if (delegate != null)
{
delegate.setDataRelation(this.relation);
delegate.notifyQueryOpenListeners(true);
}
try
{
open();
}
catch (ErrorConditionException ece)
{
close();
ErrorManager.recordOrShowDatabaseError(7312, String.format(errMsg, ""), true, false);
return logical.of(false);
}
// make one time deferred reposition for registered listeners if required
for (int i = 0; i < openedListeners.size(); i++)
{
QueryOpenedListener listener = openedListeners.get(i);
listener.afterQueryOpen();
}
return logical.of(true);
}
/**
* 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.
*/
public character indexInformation()
{
return indexInformation(new integer(1));
}
/**
* 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.
*/
public character indexInformation(int n)
{
return indexInformation(new integer(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.
*/
public character indexInformation(NumberType n)
{
if (delegate != null && delegate != DEFAULT_DELEGATE)
{
if (this.closed)
{
getDelegate().notifyQueryOpenListeners(false);
}
}
else
{
ErrorManager.recordOrShowDatabaseError(
7362,
"INDEX-INFORMATION requires query " + qname +
" to be QUERY-PREPARED or open and defined with RCODE-INFORMATION",
true, false
);
return new character();
}
int val = n.intValue();
int tableCount = getDelegate().getTableCount();
if (val < 1 || val > tableCount)
{
ErrorManager.recordOrShowError(7361,
String.format("Query method argument must be the name of a query buffer or an " +
"integer from 1 to %d for query %s",
tableCount,
name == null ? "?" : name),
false,
false);
return new character();
}
character res = getDelegate().indexInformation(n);
if (res.isUnknown())
{
res.assign(IndexHelper.WHOLE_INDEX_PREFIX + "default");
}
return res;
}
/**
* Conversion of FORWARD-ONLY attribute (KW_FWD_ONLY).
*
* Getter of FORWARD-ONLY attribute.
*
* @return current value of FORWARD-ONLY attribute.
*/
public logical forwardOnly()
{
return logical.of(forwardOnly);
}
/**
* Conversion of FORWARD-ONLY attribute (KW_FWD_ONLY).
*
* Setter of FORWARD-ONLY attribute.
*
* @param forwardOnly
* New value of FORWARD-ONLY attribute.
*/
public void changeForwardOnly(logical forwardOnly)
{
if (forwardOnly.isUnknown())
{
final String errMsg = "Unable to assign UNKNOWN value to attribute FORWARD-ONLY on QUERY widget";
// this does not exhitibit 'database behavior' related to throwing structured exceptions
// - see recordOrShowDatabaseError'
ErrorManager.recordOrShowError(4083, errMsg, false, true, false);
return;
}
if (!closed || browsed)
{
String msg1 = "Forward only status may not be changed while query %s is open or being browsed";
msg1 = String.format(msg1, qname);
final String msg2 = "Unable to set attribute FORWARD-ONLY in widget of type QUERY";
ErrorManager.recordOrShowError(new int[] { 12354, 3131 },
new String[] { msg1, msg2 },
false, false, true);
return;
}
setForwardOnly(forwardOnly.booleanValue());
}
/**
* Set the forward-only attribute for all delegate queries assigned to this wrapper.
*
* @param value
* <code>true</code> to enable forward-only, <code>false</code> to disable it.
*/
public void setForwardOnly(boolean value)
{
forwardOnly = value;
if (delegate != null)
{
getDelegate().setForwardOnly(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()
{
return forwardOnly;
}
/**
* Conversion of FORWARD-ONLY attribute (KW_FWD_ONLY).
*
* Setter of FORWARD-ONLY attribute.
*
* @param forwardOnly
* New value of FORWARD-ONLY attribute.
*/
public void changeForwardOnly(boolean forwardOnly)
{
changeForwardOnly(logical.of(forwardOnly));
}
/**
* Conversion of PREPARE_STRING attribute (KW_PREP_STR).
*
* Getter of PREPARE_STRING attribute.
*
* @return current value of PREPARE_STRING attribute.
*/
public character prepareString()
{
return new character(prepareString);
}
/**
* Getter for the CACHE attribute.
*
* @return See above.
*/
@Override
public integer getCache()
{
UnimplementedFeature.missing("QUERY:CACHE");
return new integer();
}
/**
* Setter for the CACHE attribute.
*
* @param n
* The cache value.
*/
@Override
public void setCache(integer n)
{
UnimplementedFeature.missing("QUERY:CACHE");
}
/**
* Setter for the CACHE attribute.
*
* @param n
* The cache value.
*/
@Override
public void setCache(long n)
{
UnimplementedFeature.missing("QUERY:CACHE");
}
/**
* Conversion of IS-OPEN attribute (KW_IS_OPEN).
*
* Getter of IS-OPEN attribute.
*
* @return current value of IS-OPEN attribute.
*/
public logical isOpen()
{
return logical.of(!closed);
}
/**
* Get the value of the ADM-DATA attribute.
*
* @return See above.
*/
@Override
public character getADMData()
{
return new character(admData);
}
/**
* Set the value of the ADM-DATA attribute.
*
* @param value
* The new value.
*/
@Override
public void setADMData(String value)
{
this.admData = value;
}
/**
* Set the value of the ADM-DATA attribute.
*
* @param value
* The new value.
*/
@Override
public void setADMData(character value)
{
this.admData = value.toJavaType();
}
/**
* Gets the the unique ID number associated to this object by the underlying system. Not the
* same as the handle value itself.
*
* @return The integer number of the children.
*/
@Override
public integer getUniqueID()
{
if (uniqueID == null)
{
this.uniqueID = UniqueIdGenerator.getUniqueId(IdKind.QUERY);
}
return new integer(uniqueID);
}
/**
* Delete the resource.
*
* @return <code>true</code> if the resource was deleted.
*/
@Override
protected boolean resourceDelete()
{
if (!dynamic && !implicitDeletion())
{
// static queries can't be deleted.
// although a static query handle obtained via HANDLE attribute can be deleted and a
// subsequent access of the HANDLE attribute on the static query returns a handle with a
// different ID, P2J doesn't allow static queries to be deleted (at least until we need
// to implement this too).
return false;
}
// remove the 'last query' from the BufferImpl.lastQuery
for (int i = 0; i < buffers.size(); i++)
{
Buffer buf = buffers.get(i);
((BufferImpl) buf).resetLastQuery(this);
}
// perform cleanup only when the query gets deleted
cleanup();
notifyQueryDeleted();
resetQuery();
// all queries can be deleted
this.valid = false;
ControlFlowOps.invalidateCallSiteCache(this);
// release the delegate, if closed
if (closed)
{
this.delegate = null;
}
return true;
}
/**
* 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>.
*/
@Override
public boolean _getNext()
{
if (!canGet())
{
return false;
}
advanced = true;
boolean ret = getDelegate()._getNext();
maybeFireCallback();
return ret;
}
/**
* 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 (?).
*/
public logical getNext(LockType lockType)
{
if (!canGet())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getNext(lockType);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getNext(long lock)
{
if (!canGet())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getNext(lock);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getNext(NumberType lock)
{
if (!canGet())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getNext(lock);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getNext(long lock, long nowait)
{
if (!canGet())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getNext(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getNext(long lock, NumberType nowait)
{
if (!canGet())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getNext(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getNext(NumberType lock, long nowait)
{
if (!canGet())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getNext(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getNext(NumberType lock, NumberType nowait)
{
if (!canGet())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getNext(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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 (?).
*/
public logical getPrevious()
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getPrevious();
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getPrevious(long lock)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getPrevious(lock);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getPrevious(LockType lockType)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getPrevious(lockType);
maybeFireCallback();
return ret;
}
/**
* 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 thgetPe 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.
*/
public logical getPrevious(NumberType lock)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getPrevious(lock);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getPrevious(long lock, long nowait)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getPrevious(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getPrevious(NumberType lock, long nowait)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getPrevious(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getPrevious(long lock, NumberType nowait)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getPrevious(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getPrevious(NumberType lock, NumberType nowait)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getPrevious(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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 (?).
*/
public logical getFirst()
{
if (!canGet() || !canGetFirst())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getFirst();
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getFirst(long lock)
{
if (!canGet() || !canGetFirst())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getFirst(lock);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getFirst(NumberType lock)
{
if (!canGet() || !canGetFirst())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getFirst(lock);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getFirst(LockType lockType)
{
if (!canGet() || !canGetFirst())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getFirst(lockType);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getFirst(long lock, long nowait)
{
if (!canGet() || !canGetFirst())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getFirst(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getFirst(NumberType lock, long nowait)
{
if (!canGet() || !canGetFirst())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getFirst(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getFirst(long lock, NumberType nowait)
{
if (!canGet() || !canGetFirst())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getFirst(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getFirst(NumberType lock, NumberType nowait)
{
if (!canGet() || !canGetFirst())
{
return logical.of(false);
}
advanced = true;
logical ret = getDelegate().getFirst(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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 (?).
*/
public logical getLast()
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getLast();
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getLast(long lock)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getLast(lock);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getLast(NumberType lock)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getLast(lock);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getLast(LockType lockType)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getLast(lockType);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getLast(long lock, long nowait)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getLast(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getLast(NumberType lock, long nowait)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getLast(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getLast(long lock, NumberType nowait)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getLast(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
public logical getLast(NumberType lock, NumberType nowait)
{
if (!canGet() || !canLastOrPrev())
{
return logical.of(false);
}
logical ret = getDelegate().getLast(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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>.
*/
public logical getCurrent()
{
if (!canGet())
{
return logical.of(false);
}
logical ret = getDelegate().getCurrent();
maybeFireCallback();
return ret;
}
/**
* 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>.
*/
public logical getCurrent(long lock)
{
if (!canGet())
{
return logical.of(false);
}
logical ret = getDelegate().getCurrent(lock);
maybeFireCallback();
return ret;
}
/**
* 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>.
*/
public logical getCurrent(NumberType lock)
{
if (!canGet())
{
return logical.of(false);
}
logical ret = getDelegate().getCurrent(lock);
maybeFireCallback();
return ret;
}
/**
* Conversion of GET-CURRENT() method (KW_GET_CUR).
*
* Refetches the current record or records associated with the query.
*
* @param lockType of LockType
*
* @return <code>true</code> if GET-CURRENT() succeeds, else <code>false</code>.
*/
public logical getCurrent(LockType lockType)
{
if (!canGet())
{
return logical.of(false);
}
logical ret = getDelegate().getCurrent(lockType);
maybeFireCallback();
return ret;
}
/**
* 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>.
*/
public logical getCurrent(long lock, long nowait)
{
if (!canGet())
{
return logical.of(false);
}
logical ret = getDelegate().getCurrent(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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>.
*/
public logical getCurrent(NumberType lock, long nowait)
{
if (!canGet())
{
return logical.of(false);
}
logical ret = getDelegate().getCurrent(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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>.
*/
public logical getCurrent(long lock, NumberType nowait)
{
if (!canGet())
{
return logical.of(false);
}
logical ret = getDelegate().getCurrent(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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>.
*/
public logical getCurrent(NumberType lock, NumberType nowait)
{
if (!canGet())
{
return logical.of(false);
}
logical ret = getDelegate().getCurrent(lock, nowait);
maybeFireCallback();
return ret;
}
/**
* 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.
*/
@Override
public logical createResultListEntry()
{
if (externalResultListHandler != null)
{
return externalResultListHandler.createResultListEntry();
}
if (!isOpen().booleanValue())
{
return logical.of(false);
}
else if (!isScrolling())
{
UnimplementedFeature.partial(
"CREATE-RESULT-LIST-ENTRY is not implemented for non-scrolling queries");
return logical.of(false);
}
return createResultListEntryWorker();
}
/**
* Calls delegate's {@link P2JQuery#createResultListEntry()}.
*
* @return result of execution of delegate's {@link P2JQuery#createResultListEntry()}.
*/
public logical createResultListEntryWorker()
{
return getDelegate().createResultListEntry();
}
/**
* Calls delegate's {@link P2JQuery#deleteResultListEntry()}.
*
* @return result of execution of delegate's {@link P2JQuery#deleteResultListEntry()}.
*/
public logical deleteResultListEntryWorker()
{
return getDelegate().deleteResultListEntry();
}
/**
* Deletes the current row of a query's result list. Implements the 4GL
* DELETE-RESULT-LIST-ENTRY() method.
*
* @return <code>true</code> on success.
*/
@Override
public logical deleteResultListEntry()
{
if (externalResultListHandler != null)
{
return externalResultListHandler.deleteResultListEntry();
}
if (!canGet())
{
return logical.of(false);
}
return deleteResultListEntryWorker();
}
/**
* 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.
*/
@Override
public logical deleteResultListEntry(boolean allowBetweenRows)
{
if (!canGet())
{
return logical.of(false);
}
return getDelegate().deleteResultListEntry(allowBetweenRows);
}
/**
* 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.
*/
@Override
public void setParameterFilter(ParameterFilter parameterFilter)
{
getDelegate().setParameterFilter(parameterFilter);
}
/**
* Conversion of NUM-BUFFERS() method (KW_NUM_BUFF).
*
* @return the number of buffers in a query or DataSet object.
*/
public integer numBuffers()
{
return dynamic || dynamicDelegate || delegate == DEFAULT_DELEGATE ? new integer(buffers.size())
: getDelegate().numBuffers();
}
/**
* Setter for SKIP-DELETED-RECORD query attribute.
*
* @param on
* New value for the attribute.
*/
@Override
public void setSkipDeletedRecord(logical on)
{
if (on == null || on.isUnknown())
{
ErrorManager.recordOrShowError(4083, "SKIP-DELETED-RECORD", "QUERY widget");
return; // attribute remains unchanged
}
skipDeletedRecordDisposition = on.booleanValue();
if (delegate != null)
{
delegate.setSkipDeletedRecord(on);
}
}
/**
* 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.
*
* @param on
* if {@code true} the deleted rows will not be returned because the query is managed by the
* browse widget.
*/
@Override
public void setFillingBrowseRows(boolean on)
{
if (delegate != null)
{
delegate.setFillingBrowseRows(on);
}
}
/**
* Checks whether 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.
*
* @return {@code true} if the deleted rows will not be returned because the query is managed by the
* browse widget.
*/
public boolean isFillingBrowseRows()
{
return delegate != null && delegate.isFillingBrowseRows();
}
/**
* Get value of SKIP-DELETED-RECORD attribute of the query.
*
* @return the value of SKIP-DELETED-RECORD attribute of the query.
*/
@Override
public logical isSkipDeletedRecord()
{
if (delegate == null || delegate == DEFAULT_DELEGATE)
{
return logical.of(skipDeletedRecordDisposition);
}
return delegate.isSkipDeletedRecord();
}
/**
* Associates an internal procedure with an ABL callback event.
* <p>
* This method returns false if the event name is not valid.
*
* @param event
* The event name, must evaluate to one of the events supported by implementing object.
* @param proc
* The internal procedure to be executed for this event, which will be executed using
* the current THIS-PROCEDURE reference. To remove a callback mapping, set the this
* parameter to the empty string.
*
* @return {@code true} if the event was registered.
*/
@Override
public logical setCallbackProcedure(String event, String proc)
{
return setCallbackProcedure(event, proc, null);
}
/**
* Associates an internal procedure with an ABL callback event.
* <p>
* This method returns false if the event name is not valid.
*
* @param event
* The event name.
* @param proc
* The internal procedure to be executed for this event, which will be executed using
* the current THIS-PROCEDURE reference. To remove a callback mapping, set the this
* parameter to the empty string.
*
* @return {@code true} if the event was registered.
*/
@Override
public logical setCallbackProcedure(String event, character proc)
{
return setCallbackProcedure(event, proc.toJavaType(), null);
}
/**
* Associates an internal procedure with an ABL callback event.
* <p>
* This method returns false if the event name is not valid.
*
* @param event
* The event name.
* @param proc
* The internal procedure to be executed for this event, which will be executed using
* the current THIS-PROCEDURE reference. To remove a callback mapping, set the this
* parameter to the empty string.
*
* @return {@code true} if the event was registered.
*/
@Override
public logical setCallbackProcedure(character event, character proc)
{
return setCallbackProcedure(event.toJavaType(), proc.toJavaType(), null);
}
/**
* Associates an internal procedure with an ABL callback event.
* <p>
* This method returns false if the event name is not valid or if the procedure's context is
* not a valid handle.
*
* @param event
* The event name, must evaluate to one of the events supported by implementing object.
* @param proc
* The internal procedure to be executed for this event. To remove a callback
* mapping, set the this parameter to the empty string.
* @param context
* The procedure handle where the internal procedure will be searched and executed.
*
* @return {@code true} if the event was registered.
*/
@Override
public logical setCallbackProcedure(character event, String proc, handle context)
{
return setCallbackProcedure(event.toJavaType(), proc, context);
}
/**
* Associates an internal procedure with an ABL callback event.
* <p>
* This method returns false if the event name is not valid or if the procedure's context is
* not a valid handle.
*
* @param event
* The event name.
* @param proc
* The internal procedure to be executed for this event, which will be executed using
* the current THIS-PROCEDURE reference. To remove a callback mapping, set the this
* parameter to the empty string.
* @param context
* The procedure handle where the internal procedure will be searched and executed.
*
* @return {@code true} if the event was registered.
*/
@Override
public logical setCallbackProcedure(String event, character proc, handle context)
{
return setCallbackProcedure(event, proc.toJavaType(), context);
}
/**
* Associates an internal procedure with an ABL callback event.
* <p>
* This method returns false if the event name is not valid or if the procedure's context is not a valid
* handle.
*
* @param event
* The event name.
* @param proc
* The internal procedure to be executed for this event, which will be executed using the current
* THIS-PROCEDURE reference. To remove a callback mapping, set the this parameter to the empty
* string.
* @param context
* The procedure handle where the internal procedure will be searched and executed.
*
* @return {@code true} if the event was registered.
*/
@Override
public logical setCallbackProcedure(character event, character proc, handle context)
{
return setCallbackProcedure(event.toJavaType(), proc.toJavaType(), context);
}
/**
* Applies a callback procedure, which allows execution of a defined event without duplicating
* the event procedure definition.
*
* @param eventName
* The event whose callback will be called.
*
* @return {@code true} if operation is successful.
*/
@Override
public logical applyCallback(Text eventName)
{
return applyCallback(eventName.toJavaType());
}
/**
* Retrieves the name of the internal procedure associated with the ABL callback for the
* specified event.
*
* @param eventName
* The name of the event.
*
* @return the name of the internal procedure associated with specified event.
*/
@Override
public character getCallbackProcName(Text eventName)
{
return getCallbackProcName(eventName.toJavaType());
}
/**
* Retrieves the handle of the procedure that contains the internal procedure associated
* with the ABL callback for the specified event
*
* @param eventName
* The name of the event.
*
* @return a handle to the procedure that contains the callback procedure.
*/
@Override
public handle getCallbackProcContext(Text eventName)
{
return getCallbackProcContext(eventName.toJavaType());
}
/**
* Configures a callback. Creates an association between a method within a class instance or
* an internal procedure within a persistent procedure, with an ABL callback event.
*
* @param callbackName
* The name of a callback.
* @param routineName
* The name of a method or an internal procedure to be associated.
* @param context
* The context in which the callback will be executed.
*
* @return {@code true} if operation is successful and {@code false} if the parameters are
* invalid.
*/
@Override
public logical setCallback(Text callbackName, Text routineName, object<?> context)
{
return setCallback(callbackName.toJavaType(), routineName.toJavaType(), context);
}
/**
* Configures a callback. Creates an association between a method within a class instance or
* an internal procedure within a persistent procedure, with an ABL callback event.
*
* @param callbackName
* The name of a callback.
* @param routineName
* The name of a method or an internal procedure to be associated.
* @param context
* The context in which the callback will be executed.
*
* @return {@code true} if operation is successful and {@code false} if the parameters are
* invalid.
*/
@Override
public logical setCallback(String callbackName, String routineName, handle context)
{
return setCallbackProcedure(callbackName, routineName, context);
}
/**
* Configures a callback. Creates an association between a method within a class instance or
* an internal procedure within a persistent procedure, with an ABL callback event.
*
* @param callbackName
* The name of a callback.
* @param routineName
* The name of a method or an internal procedure to be associated.
* @param context
* The context in which the callback will be executed.
*
* @return {@code true} if operation is successful and {@code false} if the parameters are
* invalid.
*/
@Override
public logical setCallback(Text callbackName, Text routineName, handle context)
{
return setCallbackProcedure(callbackName.toJavaType(), routineName.toJavaType(), context);
}
/**
* Configures a callback. Creates an association between a method within a class instance or
* an internal procedure within a persistent procedure, with an ABL callback event.
*
* @param callbackName
* The name of a callback.
* @param routineName
* The name of a method or an internal procedure to be associated.
* @param context
* The context in which the callback will be executed.
*
* @return {@code true} if operation is successful and {@code false} if the parameters are
* invalid.
*/
@Override
public logical setCallback(String callbackName, Text routineName, handle context)
{
return setCallbackProcedure(callbackName, routineName.toJavaType(), context);
}
/**
* Configures a callback. Creates an association between a method within a class instance or
* an internal procedure within a persistent procedure, with an ABL callback event.
*
* @param callbackName
* The name of a callback.
* @param routineName
* The name of a method or an internal procedure to be associated.
*
* @return {@code true} if operation is successful and {@code false} if the parameters are
* invalid.
*/
@Override
public logical setCallback(String callbackName, String routineName)
{
return setCallback(callbackName, routineName, (object<?>) null);
}
/**
* Configures a callback. Creates an association between a method within a class instance or
* an internal procedure within a persistent procedure, with an ABL callback event.
*
* @param callbackName
* The name of a callback.
* @param routineName
* The name of a method or an internal procedure to be associated.
*
* @return {@code true} if operation is successful and {@code false} if the parameters are
* invalid.
*/
@Override
public logical setCallback(Text callbackName, Text routineName)
{
return setCallback(callbackName.toJavaType(), routineName.toJavaType(), (object<?>) null);
}
/**
* Configures a callback. Creates an association between a method within a class instance or
* an internal procedure within a persistent procedure, with an ABL callback event.
*
* @param callbackName
* The name of a callback.
* @param routineName
* The name of a method or an internal procedure to be associated.
*
* @return {@code true} if operation is successful and {@code false} if the parameters are
* invalid.
*/
@Override
public logical setCallback(Text callbackName, String routineName)
{
return setCallback(callbackName.toJavaType(), routineName);
}
/**
* Configures a callback. Creates an association between a method within a class instance or
* an internal procedure within a persistent procedure, with an ABL callback event.
*
* @param callbackName
* The name of a callback.
* @param routineName
* The name of a method or an internal procedure to be associated.
*
* @return {@code true} if operation is successful and {@code false} if the parameters are
* invalid.
*/
@Override
public logical setCallback(String callbackName, Text routineName)
{
return setCallback(callbackName, routineName.toJavaType());
}
/**
* Configures a callback. Creates an association between a method within a class instance or
* an internal procedure within a persistent procedure, with an ABL callback event.
*
* @param callbackName
* The name of a callback.
* @param routineName
* The name of a method or an internal procedure to be associated.
* @param context
* The context in which the callback will be executed.
*
* @return {@code true} if operation is successful and {@code false} if the parameters are
* invalid.
*/
@Override
public logical setCallback(String callbackName, Text routineName, object<?> context)
{
return setCallback(callbackName, routineName.toJavaType(), context);
}
/**
* Configures a callback. Creates an association between a method within a class instance or
* an internal procedure within a persistent procedure, with an ABL callback event.
*
* @param callbackName
* The name of a callback.
* @param routineName
* The name of a method or an internal procedure to be associated.
* @param context
* The context in which the callback will be executed.
*
* @return {@code true} if operation is successful and {@code false} if the parameters are
* invalid.
*/
@Override
public logical setCallback(Text callbackName, String routineName, object<?> context)
{
return setCallback(callbackName.toJavaType(), routineName, context);
}
/**
* Configures a callback. Creates an association between a method within a class instance or
* an internal procedure within a persistent procedure, with an ABL callback event.
*
* @param callbackName
* The name of a callback.
* @param routineName
* The name of a method or an internal procedure to be associated.
* @param context
* The context in which the callback will be executed.
*
* @return {@code true} if operation is successful and {@code false} if the parameters are
* invalid.
*/
@Override
public logical setCallback(Text callbackName, String routineName, handle context)
{
return setCallback(callbackName.toJavaType(), routineName, context);
}
/**
* Associates an internal procedure with an ABL callback event.
* <p>
* This method returns false if the event name is not valid.
*
* @param event
* The event name.
* @param proc
* The internal procedure to be executed for this event, which will be executed using
* the current THIS-PROCEDURE reference. To remove a callback mapping, set the this
* parameter to the empty string.
*
* @return {@code true} if the event was registered.
*/
@Override
public logical setCallbackProcedure(character event, String proc)
{
return setCallbackProcedure(event.toJavaType(), proc, null);
}
/**
* Associates an internal procedure with an ABL callback event.
*
* @param eventName
* The eventName of the event.
* @param callback
* The eventName of the internal procedure associated with the callback event.
* @param context
* A handle to a procedure that contains the internal procedure specified by {@code callback}. If
* not specified, {@code THIS-PROCEDURE} is used as the procedure context.
*
* @return {@code true} when the method ends with success.
*/
@Override
public logical setCallbackProcedure(String eventName, String callback, handle context)
{
if (!isCallbackName(eventName))
{
return logical.of(false);
}
if (getDataSet() == null)
{
ErrorManager.recordOrShowError(11951);
// SET-CALLBACK-PROCEDURE is only valid for buffers that are members of a dataset.
return logical.of(false);
}
if (callback != null)
{
if (context == null || context.isUnknown())
{
// defaulting to THIS-PROCEDURE
context = pm.thisProcedure();
}
else
{
if (!context._isValid() || !(context.getResource() instanceof PersistentProcedure))
{
ErrorManager.recordOrShowError(13273);
// Third argument to SET-CALLBACK must be a valid procedure handle or object reference.
return logical.of(false);
}
}
this.callback = new CallbackData(callback, context, null, OFF_END_CALL_SITE);
}
return logical.of(true);
}
/**
* Configures a callback. Creates an association between a method within a class instance or an internal
* procedure within a persistent procedure, with an ABL callback event.
*
* @param callbackName
* The name of a callback.
* @param routineName
* The name of a method or an internal procedure to be associated.
* @param context
* The context in which the callback will be executed.
*
* @return {@code true} if {@code callbackName} is a correct callback name. The rest of parameters are
* ignored (note: manual states otherwise).
*/
@Override
public logical setCallback(String callbackName, String routineName, object<?> context)
{
if (!isCallbackName(callbackName))
{
return logical.of(false);
}
if (getDataSet() == null)
{
ErrorManager.recordOrShowError(11951);
// SET-CALLBACK-PROCEDURE is only valid for buffers that are members of a dataset.
return logical.of(false);
}
if (routineName != null)
{
CallbackData cbd;
if (context == null || context.isUnknown())
{
// defaulting to THIS-OBJECT or to THIS-PROCEDURE, depending on the context
if (ObjectOps.thisObject().isUnknown())
{
cbd = new CallbackData(routineName, pm.thisProcedure(), null, OFF_END_CALL_SITE);
}
else
{
cbd = new CallbackData(routineName, null, ObjectOps.thisObject(), null);
}
}
else
{
cbd = new CallbackData(routineName, null, context, null);
}
this.callback = cbd;
}
return logical.of(true);
}
/**
* Applies a callback procedure, which allows execution of a defined event without duplicating the event
* procedure definition.
*
* @param eventName
* The event whose callback will be called.
*
* @return {@code true} if operation is successful.
*/
public logical applyCallback(String eventName)
{
DataSet ds = getDataSet();
if (ds == null)
{
ErrorManager.recordOrShowError(11949);
// APPLY-CALLBACK is only for buffers that are members of datasets.
return logical.of(false);
}
if (!isCallbackName(eventName))
{
return logical.of(false);
}
return logical.of(invokeCallback(asHandle(), this.callback));
}
/**
* Retrieves the name of the internal procedure associated with the ABL callback for the specified event.
*
* @param eventName
* The name of the event.
*
* @return the name of the internal procedure associated with specified event.
*/
@Override
public character getCallbackProcName(String eventName)
{
if (getDataSet() == null)
{
if (buffers != null && buffers.size() > 0)
{
ErrorManager.recordOrShowError(12788, getName(), ((BufferImpl) buffers.get(0)).doGetName());
// OFF-END CALLBACK not supported for query <name> whose buffer <name> is not in a dataset.
return new character();
}
}
if (!isCallbackName(eventName))
{
return new character();
}
if (this.callback == null)
{
return new character();
}
return new character(this.callback.getTarget());
}
/**
* Retrieves the handle of the procedure that contains the internal procedure associated with the ABL
* callback for the specified event
*
* @param eventName
* The name of the event.
*
* @return a handle to the procedure that contains the callback procedure.
*/
@Override
public handle getCallbackProcContext(String eventName)
{
if (getDataSet() == null)
{
if (buffers != null && buffers.size() > 0)
{
ErrorManager.recordOrShowError(12788, getName(), ((BufferImpl) buffers.get(0)).doGetName());
// OFF-END CALLBACK not supported for query <name> whose buffer <name> is not in a dataset.
return new handle();
}
}
if (!isCallbackName(eventName))
{
return new handle();
}
if (this.callback == null || this.callback.getProcedure() == null)
{
return new handle();
}
return new handle(this.callback.getProcedure());
}
/**
* 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)
{
getDelegate().include(dmo, 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)
{
getDelegate().exclude(dmo, fields);
}
/**
* Get a list of all buffers in this query.
*
* @return The list of buffers.
*/
@Override
public RecordBuffer[] getRecordBuffers()
{
RecordBuffer[] bufs = new RecordBuffer[buffers.size()];
for (int i = 0; i < bufs.length; i++)
{
bufs[i] = ((BufferReference) buffers.get(i)).buffer();
}
return bufs;
}
/**
* Test whether the OFF-END event occurred and if so, fire the callback if one is defined.
*/
private void maybeFireCallback()
{
if (!offEnd && getDelegate()._isOffEnd())
{
offEnd = true;
if (getDataSet() != null && callback != null)
{
invokeCallback(asHandle(), this.callback);
}
}
}
/**
* Add the buffers associated with the given query to this QUERY's buffer list.
* <p>
* Will be a no-op when this is a {@link #dynamic} query.
*
* @param query
* The P2J query from which the buffers are loaded.
* @param clear
* When <code>true</code>, it will clear the {@link #buffers} list and the predicate.
*/
private void addBuffers(Joinable query, boolean clear)
{
if (dynamic)
{
return;
}
if (clear)
{
resetQuery();
}
for (RecordBuffer buf : query.getRecordBuffers())
{
this.buffers.add((Buffer) buf.getDMOProxy());
}
}
/**
* Identify the buffer which matches the given buffer name. Use an instance of the
* {@code BufferManager} to identify the proper buffer.
*
* @param bm
* An instance of the {@code BufferManager}. This can be {@code null}, case in which
* it will be initialized with a buffer manager from the local context.
* @param bufName
* The buffer name which should be used to identify the searched buffer.
* @param bufIdx
* The index of the buffer inside the query, such that in case the buffer
* searching fails, it will prompt and error indicating the buffer index.
*
* @return A search buffer instance according to the provide name, or null if no buffer was found.
*/
private Buffer parseBuffer(BufferManager bm, String bufName, int bufIdx)
{
if (bm == null)
{
bm = BufferManager.get();
}
Buffer crtBuff;
bufName = TextOps.rightTrimNative(bufName);
RecordBuffer rb = bm.lookupByName(bufName);
if (rb != null)
{
crtBuff = (Buffer) rb.getDMOProxy();
}
else
{
ErrorManager.recordOrShowError(7319, Integer.toString(bufIdx));
// ADD/SET-BUFFERS argument <argnumber> was invalid or not found.
return null;
}
return crtBuff;
}
/**
* Check if the resource referenced by given handle is a valid {@link Buffer}.
*
* @param h
* The handle to be checked.
* @param idx
* The index of this handle in a {@link #setBuffers} call.
*
* @return <code>true</code> if the handle is valid and the referrent is a {@link Buffer}.
*/
private boolean validBuffer(handle h, int idx)
{
boolean valid = h._isValid() && h.getResource() instanceof Buffer;
if (!valid)
{
final String errMsg = "ADD/SET-BUFFERS argument %d was invalid or not found";
ErrorManager.recordOrShowDatabaseError(7319, String.format(errMsg, idx), false, false);
}
return valid;
}
/**
* Check if a buffer can be added to this query.
*
* @return <code>true</code> if a buffer can be added.
*/
private boolean canAddBuffer()
{
if (!dynamic)
{
final String errMsg = "ADD/SET-BUFFERS may not be used on static query %s";
ErrorManager.recordOrShowDatabaseError(7317, String.format(errMsg, qname), false, false);
}
return dynamic;
}
/**
* Check if the query is opened. If is not open, an error message is displayed and an ERROR
* condition is raised. If the query is forward-only, then it is not scrolling and another
* ERROR condition is raised.
*
* @return <code>true</code> if the query is not closed and not forward-only.
*/
private boolean canReposition()
{
// TODO: the rowid is evaluated before checking if the query is closed or not!
if (closed)
{
final String errMsg = "Cannot reposition on query %s, which is not opened";
if (dynamic || dynamicDelegate)
{
ErrorManager.recordOrShowError(3163, String.format(errMsg, qname), false, false);
}
else
{
ErrorManager.recordOrThrowError(3163, String.format(errMsg, qname), false, false);
}
}
if (forwardOnly)
{
final String errMsg = "Cannot reposition on query %s which is not defined as SCROLLING";
ErrorManager.recordOrThrowError(3164, String.format(errMsg, qname), false, false);
return false;
}
return true;
}
/**
* Check if the query is opened. If is not open, an error message is displayed (but no error
* recorded).
*
* @return <code>true</code> if the query is not closed.
*/
private boolean canGet()
{
if (closed)
{
final String errMsg = "Cannot run GET methods on query %s until it is opened";
ErrorManager.recordOrShowDatabaseError(7313, String.format(errMsg, qname), false, false);
}
return !closed;
}
/**
* Check if the query can be advanced via GET-FIRST.
*
* @return <code>true</code> if the query can be advanced via GET-FIRST.
*/
private boolean canGetFirst()
{
if (forwardOnly && advanced)
{
final String errMsg =
"Cannot move Query %s back to FIRST when FORWARD-ONLY or -noautoreslist enabled";
if (dynamic || dynamicDelegate)
{
ErrorManager.recordOrShowError(12394, String.format(errMsg, qname), false, false);
}
else
{
ErrorManager.recordOrThrowError(12394, String.format(errMsg, qname), false, false);
}
return false;
}
return true;
}
/**
* Check if the query is opened. If is not open, an error message is displayed (but no error
* recorded).
*
* @return <code>true</code> if the query is not closed.
*/
private boolean canGetStmt()
{
if (closed)
{
final String errMsg = "Cannot Get on query %s which is not opened";
if (dynamic || dynamicDelegate)
{
ErrorManager.recordOrShowError(3159, String.format(errMsg, qname), false, false);
}
else
{
ErrorManager.recordOrThrowError(3159, String.format(errMsg, qname), false, false);
}
}
return !closed;
}
/**
* Check if the GET-LAST or GET-FIRST can be executed.
*
* @return <code>true</code> if not in forward-only mode.
*/
private boolean canLastOrPrev()
{
if (forwardOnly)
{
final String errMsg =
"Cannot LAST or PREV Query %s when FORWARD-ONLY or -noautoreslist or BREAK BY enabled";
if (dynamic || dynamicDelegate)
{
ErrorManager.recordOrShowError(12393, String.format(errMsg, qname), false, false);
}
else
{
ErrorManager.recordOrThrowError(12393, String.format(errMsg, qname), false, false);
}
}
return !forwardOnly;
}
/**
* Assign a <code>P2JQuery</code> instance as this container's active
* delegate query. Set any deferred state which has been set for the
* wrapper, such as scrollability and whether delegate should error out on
* failed first/last/unique retrievals.
*
* @param delegate
* New delegate query.
*/
private void assignImpl(P2JQuery delegate)
{
assignImpl(delegate, true);
}
/**
* Assign a <code>P2JQuery</code> instance as this container's active
* delegate query. Set any deferred state which has been set for the
* wrapper, such as scrollability and whether delegate should error out on
* failed first/last/unique retrievals.
*
* @param delegate
* New delegate query.
* @param open
* <code>true</code> if the query is considered to be open.
*/
private void assignImpl(P2JQuery delegate, boolean open)
{
if (!closed && this.delegate != null)
{
close();
}
this.originalQueryType = null;
this.delegate = delegate;
delegate.setForwardOnly(forwardOnly);
if (scrolling)
{
delegate.setScrolling();
}
if (indexedReposition)
{
setDelegateIndexedReposition();
}
delegate.setForceDatabaseJoin(logical.of(this.forceDatabaseJoin));
delegate.setStandalone(false);
delegate.setBrowsed(browsed);
if (browsed)
{
skipDeletedRecordDisposition = false;
}
delegate.setSkipDeletedRecord(logical.of(skipDeletedRecordDisposition));
delegate.setErrorIfNull(errorIfNull);
if (browsed)
{
fetchOnReposition = true;
}
delegate.setFetchOnReposition(fetchOnReposition);
Iterator<RepositionListener> iter = repoListeners.iterator();
while (iter.hasNext())
{
RepositionListener next = iter.next();
delegate.addRepositionListener(next);
}
this.closed = !open;
}
/**
* Convenience method to access the delegate query as an instance of
* <code>CompoundQuery</code>.
*
* @return Delegate query, cast to a <code>CompoundQuery</code>.
*
* @throws IllegalStateException
* if the query delegate is not an instance of
* <code>CompoundQuery</code>.
*/
private CompoundQuery compoundDelegate()
{
try
{
return (CompoundQuery) delegate;
}
catch (ClassCastException exc)
{
throw new IllegalStateException(
"Expected compound query delegate; found " +
Utils.getUnqualifiedName(delegate.getClass()));
}
}
/**
* Convenience method to access the delegate query as an instance of
* <code>PreselectQuery</code>.
*
* @return Delegate query, cast to a <code>PreselectQuery</code>.
*
* @throws IllegalStateException
* if the query delegate is not an instance of
* <code>PreselectQuery</code>.
*/
private PreselectQuery preselectDelegate()
{
try
{
return (PreselectQuery) delegate;
}
catch (ClassCastException exc)
{
throw new IllegalStateException(
"Expected preselect query delegate; found " +
Utils.getUnqualifiedName(delegate.getClass()));
}
}
/**
* Convenience method to access the delegate query as an instance of
* <code>PresortDelegate</code>.
*
* @return Delegate query, cast to a <code>PresortDelegate</code>.
*
* @throws IllegalStateException
* if the query delegate is not an instance of
* <code>PresortDelegate</code>.
*/
private PresortDelegate presortDelegate()
{
try
{
return (PresortDelegate) delegate;
}
catch (ClassCastException exc)
{
throw new IllegalStateException(
"Expected presort query delegate; found " +
Utils.getUnqualifiedName(delegate.getClass()));
}
}
/**
* Convenience method to access the delegate query as an instance of
* <code>RandomAccessQuery</code>.
*
* @return Delegate query, cast to a <code>RandomAccessQuery</code>.
*
* @throws IllegalStateException
* if the query delegate is not an instance of
* <code>RandomAccessQuery</code>.
*/
private RandomAccessQuery randomAccessDelegate()
{
try
{
return (RandomAccessQuery) delegate;
}
catch (ClassCastException exc)
{
throw new IllegalStateException(
"Expected random access query delegate; found " +
Utils.getUnqualifiedName(delegate.getClass()));
}
}
/**
* Unregister this wrapper from the list of related queries for all participating buffers.
* If any buffer is detected to be deleted (not valid or its delete operation is in progress,
* it is removed from the buffer list).
*/
private void unregisterBufferRelatedQueries()
{
List<Buffer> toDelete = new ArrayList<>();
for (int i = 0; i < buffers.size(); i++)
{
Buffer buffer = buffers.get(i);
BufferImpl bufImpl = (BufferImpl) buffer;
RecordBuffer recordBuffer = bufImpl.buffer();
recordBuffer.unregisterRelatedQuery(this);
// remove the buffer if it was deleted or its delete operation is in progress
if (!bufImpl.valid() || bufImpl.isDeleting())
{
toDelete.add(buffer);
}
}
buffers.removeAll(toDelete);
}
/**
* Convenience method to access the current delegate query.
*
* TODO: this is a private method just returning a private member. Should be replaced with direct access which is much faster.
*
* @return Delegate query assigned to this wrapper by business logic, or the default delegate query.
*/
private P2JQuery getDelegate()
{
return delegate;
}
/**
* Get legacy query name.
*
* @return legacy query name.
*/
public String getName()
{
return qname;
}
/**
* Release the buffers. The call is forwarded to {@code delegate} query.
*/
@Override
public void releaseBuffers()
{
delegate.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.
*/
@Override
public boolean addDynamicFilter(FieldReference fr, BaseDataType val, String format)
{
if (fr == null)
{
return false;
}
return getDelegate().addDynamicFilter(fr, val, format);
}
/**
* Clears any dynamically filters added at runtime. The query predicate will be restored to its
* form from generated at conversion time.
*/
@Override
public void clearDynamicFilters()
{
getDelegate().clearDynamicFilters();
}
/**
* Clears any dynamically sort criteria added at runtime. The query sort order will be restored
* to its form from generated at conversion time.
*/
public void clearDynamicSorts()
{
if (originalQueryType != null && originalQueryType == AdaptiveQuery.class)
{
PreselectQuery pq = (PreselectQuery) getDelegate();
AdaptiveQuery aq = new AdaptiveQuery();
// initialize to create components array
assign(aq.initialize());
// add to components
ArrayList<QueryComponent> components = pq.components();
for (int i = 0; i < components.size(); i++)
{
QueryComponent comp = components.get(i);
addBuffer((Buffer) comp.getBuffer().getDMOProxy(), true);
aq.addComponent(comp);
}
return;
}
P2JQuery del = getDelegate();
if (del instanceof PreselectQuery)
{
((PreselectQuery) del).clearDynamicSortCriteria();
}
else if (del instanceof PresortDelegate)
{
((PresortDelegate) del).clearDynamicSortCriteria();
}
else
{
return; // no sorted, nothing to reset
}
}
/**
* Adds a new sorting criterion as the strongest criterion for sorting the result of this
* query. The other criteria remain queued, but with lower priority.
* <p>
* Use {@link #clearDynamicSorts} 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 new strongest criterion. The current criteria will
* be kept, but with lower priority.
* @param asc
* The direction of sorting for this criterion. Use {@code true} for ascending sort
* and {@code false} for descending sorting.
*/
public void addDynamicSort(FieldReference fr, boolean asc)
{
addDynamicSort(new FieldReference[]{fr}, new boolean[]{asc});
}
/**
* Adds new sorting criteria as the most coarse set of criteria for sorting the result of this
* query. The other criteria remain queued, but with lower priority.
* <p>
* Use {@link #clearDynamicSorts} to clean all dynamically added criteria and restore the
* sorting order of the query to its original form.
*
* @param fieldReferences
* References to fields used as new most coarse criteria. The current criteria will
* be kept, but with lower priority. Inside the array criteria are positioned from
* the most coarse to the most granular.
* @param asc
* Direction of sorting for the new criteria. Use {@code true} for ascending sort
* and {@code false} for descending sorting. Inside the array directions are
* positioned from the most coarse criterion to the most granular.
*/
public void addDynamicSort(FieldReference[] fieldReferences, boolean[] asc)
{
P2JQuery del = getDelegate();
if (del instanceof PresortDelegate)
{
for (int i = fieldReferences.length - 1; i >= 0; i--)
{
((PresortDelegate) del).addDynamicSortCriterion(fieldReferences[i], asc[i]);
}
}
else if (del instanceof CompoundQuery)
{
PresortCompoundQuery pcq = new PresortCompoundQuery();
assign(pcq.initialize());
for (int i = fieldReferences.length - 1; i >= 0; i--)
{
pcq.addDynamicSortCriterion(fieldReferences[i], asc[i]);
}
CompoundQuery cq = (CompoundQuery) del;
ArrayList<CompoundComponent> originalComponents = cq.getOriginalComponents();
for (int i = 0; i < originalComponents.size(); i++)
{
CompoundComponent comp = originalComponents.get(i);
addComponent(comp.getQuery(), comp.getIteration(), comp.isOuter());
}
}
else if (del instanceof AdaptiveQuery)
{
AdaptiveQuery aq = (AdaptiveQuery) del;
PreselectQuery pq = new PreselectQuery();
// initialize to create components array
assign(pq.initialize(aq.getSortPhrase()));
originalQueryType = AdaptiveQuery.class;
// add to components
ArrayList<QueryComponent> components = aq.components();
for (int i = 0; i < components.size(); i++)
{
QueryComponent comp = components.get(i);
addBuffer((Buffer) comp.getBuffer().getDMOProxy(), true);
pq.addComponent(comp);
}
// add dynamic sort criteria AFTER adding the components
for (int i = fieldReferences.length - 1; i >= 0; i--)
{
pq.addDynamicSortCriterion(fieldReferences[i], asc[i]);
}
}
else if (del instanceof PreselectQuery)
{
for (int i = fieldReferences.length - 1; i >= 0; i--)
{
((PreselectQuery) del).addDynamicSortCriterion(fieldReferences[i], asc[i]);
}
}
else
{
if (LOG.isLoggable(Level.WARNING))
{
LOG.warning("Failed to add dynamic sorting for " + del.getClass());
}
}
}
/**
* Adds a listener to be notified about the query wrapper events. The events are related to the wrapper
* rather to the delegate. E.g. query open event is fired when the currently assigned delegate is about to
* be opened, and the delegate may change over time.
*
* @param listener
* The listener to be notified.
*/
public void addQueryWrapperListener(QueryWrapperListener listener)
{
if (wrapperListeners == null)
{
wrapperListeners = new HashSet<>();
}
wrapperListeners.add(listener);
}
/**
* Remove a listener from being notified about the query wrapper events.
*
* @param listener
* The listener to be removed.
*/
public void removeQueryWrapperListener(QueryWrapperListener listener)
{
if (wrapperListeners == null)
{
return;
}
wrapperListeners.remove(listener);
}
/**
* Check if the resource can veto the delete or not, before attempting the {@link #delete()} call.
*
* @param ref
* The exact handle holding the reference, on which the delete is attempted.
* @param explicit
* Flag indicating this is called via <code>DELETE OBJECT</code> from the application.
*
* @return <code>false</code> if the delete is vetoed.
*/
@Override
public boolean allowDelete(handle ref, boolean explicit)
{
if (ref == null || !ref._isValid() || !(ref.getResource() instanceof QueryWrapper))
{
return super.allowDelete(ref, explicit);
}
QueryWrapper query = (QueryWrapper) ref.getResource();
boolean allow = query.isExplicit() || !explicit;
if (!allow)
{
ErrorManager.recordOrShowError(12349);
// Cannot delete a dataset relation auto-generated query. (12349)
}
return allow;
}
/**
* Test whether this is an explicit query. The implicit queries cannot be deleted in a 4GL program.
*
* @return {@code true} if this is a normal (explicitly) created query.
*/
boolean isExplicit()
{
return explicit;
}
/**
* Mark this query as implicit. By default, all queries are explicit. The implicit queries are
* queries managed automatically for DataSources. They are created and deleted without programmer
* interference.
*/
void setImplicit()
{
this.explicit = false;
}
/**
* Notify query wrapper event listeners that the query is about to be opened.
*/
void notifyBeforeOpenListeners()
{
if (wrapperListeners == null)
{
return;
}
for (QueryWrapperListener listener : wrapperListeners)
{
listener.beforeQueryOpen();
}
}
/**
* Instruct dynamic conversion to use the list of 'parent' buffers of {@code datasetBuffer} as substitution
* buffers. These are not the main buffers the query is iterating but may appear in SUBST nodes (as
* substitutions).
*
* @param datasetBuffer
* The {@code Buffer} this query is used to populate in a {@code fill()} operation. If this is
* not a database buffer or the buffer is a top-level buffer, no substitution buffers are added.
*/
void setSubstitutionBuffers(Buffer datasetBuffer)
{
substBuffers = null;
DataSet dataSet = (DataSet) datasetBuffer.dataSet().getResource();
if (dataSet == null)
{
return;
}
substBuffers = new ArrayList<>();
substBuffers.add(datasetBuffer);
List<DataRelation> parentRelations = dataSet.getRelations(datasetBuffer, false, true, false);
if (!parentRelations.isEmpty())
{
for (DataRelation rel : parentRelations)
{
substBuffers.add(rel.getParentBuffer().unwrapBuffer());
}
}
}
/**
* Instruct dynamic conversion to add a list of substitution buffers. These are not the main
* buffers the query is iterating but may appear in SUBST nodes (as substitutions).
*
* @param substs
* A list of node that the query may use in substitution nodes.
*/
void setSubstitutionBuffers(Buffer... substs)
{
substBuffers = Arrays.asList(substs);
}
/**
* Notify all registered listeners the query is deleted.
*/
protected void notifyQueryDeleted()
{
if (repoListeners != null)
{
Iterator<RepositionListener> iter = repoListeners.iterator();
while (iter.hasNext())
{
RepositionListener next = iter.next();
next.queryDeleted();
}
}
}
/**
* Invokes a callback procedure or a callback method. The callback procedure/method must have an
* {@code INPUT} parameter of type {@code DATASET} or {@code DATASET-HANDLE}. The passed parameter is this
* {@code DataSet} object.
*
* @param cbd
* A {@code CallbackData} object holding the data necessary for invocation. May be {@code null},
* in which case this method will silently return {@code yes} even though nothing is performed.
* @param self
* The object on which the event is applied (buffer or dataset).
*
* @return {@code true} if no errors were encountered during execution.
*/
protected boolean invokeCallback(handle self, CallbackData cbd)
{
if (cbd == null)
{
return true; // yep, nothing to do here
}
try
{
ErrorManager.setSilent(false);
SelfManager.pushSelf(self);
// reference already assumes input-output, do not emit append
DataSetParameter dsp = new DataSetParameter(getDataSet(), ParameterOption.BY_REFERENCE);
if (cbd.getObject() != null)
{
// TODO:
// Method '<methodname>' for callback must be valid public method. (13452)
ObjectOps.invokeStandalone(cbd.getObject(), cbd.getTarget(), "I", dsp);
}
else if (cbd.getProcedure() != null && !cbd.getProcedure().isUnknown())
{
InvokeConfig callSite = cbd.getCallSite();
InvokeConfig cfg = callSite == null ? new InvokeConfig() : callSite.clone();
cfg.setTarget(cbd.getTarget())
.setInHandle(cbd.getProcedure())
.setModes("I")
.setArguments(dsp)
.executeForResource(this);
}
// NOTE: sometimes the method return *NO* even if the callback was successfully called
return true;
}
catch (Exception e)
{
LOG.severe("", e);
return false;
}
finally
{
SelfManager.popSelf();
// Do not restore silent-mode!
}
}
/**
* Obtains the {@code Dataset} of the first buffer of this query, if this is defined.
*
* @return the {@code Dataset} of the first buffer of this query, if this is defined.
*/
private DataSet getDataSet()
{
DataSet ds = null;
if (buffers != null && buffers.size() > 0)
{
BufferImpl buffer = (BufferImpl) buffers.get(0);
if (buffer.isAfterBuffer())
{
ds = buffer._dataSet();
}
}
return ds;
}
/**
* Test whether a string is a valid CALLBACK name for a {@code DataSet Query}. This method is responsible
* for raising the 12352 error if the name specified is unknown or not {@code OFF-END} - the only supported
* event for dataset queries.
*
* @param someName
* The name to test.
*
* @return {@code true} only if {@code someName} is equals to "OFF-END".
*/
private static boolean isCallbackName(String someName)
{
if (!OFF_END_EVENT.equalsIgnoreCase(someName))
{
ErrorManager.recordOrShowError(12352, someName != null ? someName : "");
// Argument <name> to query callback method must be a valid query event name such as OFF-END
return false;
}
return true;
}
/**
* Helper for making delegate query indexed reposition while checking the eligibility.
*/
private void setDelegateIndexedReposition()
{
if (!scrolling)
{
final String errMsg = "MAX-ROWS, INDEXED-REPOSITION, etc. require query %s " +
"to be defined with SCROLLING.";
ErrorManager.noRecordOrThrowError(String.format(errMsg, qname));
}
if (getDelegate().isNativelyPreselect())
{
// silently ignore the indexed reposition optimization
}
if (delegate != null)
{
getDelegate().setIndexedReposition();
}
}
/**
* A no-op implementation of <code>P2JQuery</code> which is used as the
* default delegate for the enclosing <code>QueryWrapper</code>. This
* implementation behaves as a query which returns no results would,
* except that its <code>isValid</code> method returns <code>false</code>,
* as an indication that it is a "fake" query for those callers to whom
* this information is relevant.
*/
private static class DefaultDelegate
implements P2JQuery
{
/**
* No-op.
*/
@Override
public void clearResults()
{
}
/**
* No-op.
*/
public void setScrolling()
{
}
/**
* Indicate whether this query was defined as SCROLLING.
*
* @return <code>false</code>.
*/
public boolean isScrolling()
{
return false;
}
/**
* No-op.
*
* @param value
* <code>true</code> to enable forward-only, <code>false</code> to disable it.
*/
public void setForwardOnly(boolean value)
{
}
/**
* Method that returns a default value for the forwardOnly flag.
*
* @return <code>true</code> if forward-only is enabled, <code>false</code> otherwise.
*/
public boolean isForwardOnly()
{
return false;
}
/**
* No-op.
*/
@Override
public void setForceDatabaseJoin(logical forceDatabaseJoin)
{
}
/**
* Indicate whether this query should enforce a database join if possible.
*
* @return <code>false</code>.
*/
@Override
public logical isForceDatabaseJoin()
{
return logical.of(false);
}
/**
* No-op.
*/
@Override
public void setIndexedReposition()
{
}
/**
* Indicate whether this query is optimized using indexed reposition.
*
* @return <code>false</code>.
*/
@Override
public boolean isIndexedReposition()
{
return false;
}
/**
* No-op.
*/
public void open()
{
}
/**
* No-op.
*/
public void close()
{
}
/**
* Get the number of tables joined by this query.
*
* @return 0.
*/
public int getTableCount()
{
return 0;
}
/**
* Get all the off-end listeners associated with this query.
*
* @return the off-end listeners associated with this query.
*/
public ArrayList<QueryOffEndListener> getOffEndListeners()
{
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.
* <p>
* No-op.
*
* @param dmos
* One or more external buffers.
*
* @return {@code null}.
*/
public P2JQuery addExternalBuffers(DataModelObject... dmos)
{
return null;
}
/**
* 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.
*/
@Override
public RandomAccessQuery setMultiTenantAlternative(String where,
Supplier<logical> whereExpr,
String sort,
Object[] args)
{
return null;
}
/**
* 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 {@code null}.
*/
@Override
public P2JQuery setMultiTenantAlternative(String where, Supplier<logical> whereExpr, String sort)
{
return null;
}
/**
* No-op.
*
* @param browsed
* Not used.
*/
public void setBrowsed(boolean browsed)
{
}
/**
* Is this query associated with a browse widget or not?
*
* @return <code>false</code>.
*/
public boolean isBrowsed()
{
return false;
}
/**
* No-op.
*
* @param errorIfNull
* Not used.
*/
public void setErrorIfNull(boolean errorIfNull)
{
}
/**
* No-op.
*
* @param accum
* Not used.
*/
public void addAccumulator(Accumulator accum)
{
}
/**
* No-op.
*
* @param accum
* Not used.
* @param deferred
* Not used.
*/
public void addAccumulator(Accumulator accum, boolean deferred)
{
}
/**
* No-op.
*/
public boolean first()
{
return false;
}
/**
* No-op.
*
* @param lockType
* Not used.
*/
public boolean first(LockType lockType)
{
return false;
}
/**
* No-op.
*/
public boolean last()
{
return false;
}
/**
* No-op.
*
* @param lockType
* Not used.
*/
public boolean last(LockType lockType)
{
return false;
}
/**
* No-op.
*/
public boolean next()
{
return true;
}
/**
* No-op.
*
* @param lockType
* Not used.
*/
public boolean next(LockType lockType)
{
return true;
}
/**
* No-op.
*/
public boolean previous()
{
return false;
}
/**
* No-op.
*
* @param lockType
* Not used.
*/
public boolean previous(LockType lockType)
{
return false;
}
/**
* No-op.
*/
public boolean unique()
{
return false;
}
/**
* No-op.
*
* @param lockType
* Not used.
*/
public boolean unique(LockType lockType)
{
return false;
}
/**
* No-op.
*/
public boolean current()
{
return false;
}
/**
* No-op.
*
* @param lockType
* Not used.
*/
public boolean current(LockType lockType)
{
return false;
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasAny()
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasAny(Object[] values)
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasAny(LockType lockType)
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasAny(Object[] values, LockType lockType)
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasOne()
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasOne(Object[] values)
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasOne(LockType lockType)
{
throw new UnsupportedOperationException();
}
/**
* 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>.
*
* @throws UnsupportedOperationException
* always.
*/
public logical hasOne(Object[] values, LockType lockType)
{
throw new UnsupportedOperationException();
}
/**
* Default implementation which reports query is not set to fetch the
* next record after a reposition.
*
* @return <code>false</code>.
*/
public boolean isFetchOnReposition()
{
return false;
}
/**
* No-op.
*
* @param enable
* Not used.
*/
public void setFetchOnReposition(boolean enable)
{
}
/**
* No-op.
*
* @param listener
* Not used.
*/
public void addRepositionListener(RepositionListener listener)
{
}
/**
* No-op.
*
* @param listener
* Not used.
*/
public void removeRepositionListener(RepositionListener listener)
{
}
/**
* No-op.
*
* @param id
* Not used.
*/
public void repositionByID(recid id)
{
}
/**
* No-op.
*
* @param id1
* Not used.
* @param joinIDs
* Not used.
*/
public void repositionByID(rowid id1, rowid... joinIDs)
{
}
/**
* No-op.
*
* @param joinIDs
* Not used.
*
* @return Always {@code true}.
*/
public boolean repositionByID(Long... joinIDs)
{
return true;
}
/**
* No-op.
*
* @param row
* Not used.
*/
public void reposition(NumberType row)
{
}
/**
* No-op.
*
* @param row
* Not used.
*/
public void reposition(int row)
{
}
/**
* No-op.
*
* @param rows
* Not used.
*/
public boolean forward(NumberType rows)
{
return false;
}
/**
* No-op.
*
* @param rows
* Not used.
*/
public boolean forward(int rows)
{
return false;
}
/**
* No-op.
*
* @param rows
* Not used.
*/
public boolean backward(NumberType rows)
{
return false;
}
/**
* No-op.
*
* @param rows
* Not used.
*/
public boolean backward(int rows)
{
return false;
}
/**
* Default implementation which reports unknown value to indicate a
* closed query.
*
* @return unknown value.
*/
public integer size()
{
return (new integer());
}
/**
* Default implementation which reports unknown value as the current
* row to indicate an empty results list.
*
* @return Unknown value.
*/
public integer currentRow()
{
return currentRowImpl();
}
/**
* Default implementation which reports unknown value as the current
* row to indicate an empty results list.
*
* @return Unknown value.
*/
public integer currentRowImpl()
{
return (new integer());
}
/**
* Default implementation which reports the query is off-end.
*
* @return <code>true</code>.
*/
public logical isOffEnd()
{
return (logical.of(true));
}
/**
* Default implementation which reports the query is off-end.
*
* @return <code>true</code>.
*/
public boolean _isOffEnd()
{
return true;
}
/**
* Default implementation which reports that the query has the front
* off-end.
*
* @return {@link OffEnd#FRONT} constant.
*/
public OffEnd getOffEnd()
{
return OffEnd.FRONT;
}
/**
* Indicate whether this query preselects all of its results.
*
* @return <code>false</code>.
*/
public boolean isPreselect()
{
return false;
}
/**
* Indicate whether this query is a preselect query by its nature.
*
* @return <code>true</code>.
*/
public boolean isNativelyPreselect()
{
return false;
}
/**
* No-op.
*
* @param closed
* Not used.
* @param error
* Not used.
* @param targetRepositionRow
* Not used.
*/
public void notifyRepositionListeners(boolean closed,
boolean error,
int targetRepositionRow)
{
}
/**
* Indicate whether this query stands alone, or is the component of
* another query, or is wrapped by a query wrapper.
*
* @return <code>false</code>.
*/
public boolean isStandalone()
{
return false;
}
/**
* 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.
* <p>
* This implementation is a no-op.
*
* @param standalone
* <code>true</code> to set query as standalone;
* <code>false</code> to set query as contained.
*/
public void setStandalone(boolean standalone)
{
}
/**
* No-op.
*/
public void cleanup()
{
}
/**
* Conversion of GET-BUFFER-HANDLE() method (KW_GET_BUFH).
*
* Returns a handle of the first buffer of a query object.
*
* @return unknown buffer handle
*/
public handle bufferHandle()
{
return new handle();
}
/**
* Conversion of GET-BUFFER-HANDLE() method (KW_GET_BUFH).
*
* Returns a handle of a particular buffer of a query object.
*
* @param bufferName
* buffer-name. A CHARACTER expression that evaluates to the name
* of a buffer in the query or DataSet object.
*
* @return Unknown buffer handle.
*/
public handle bufferHandle(String bufferName)
{
return (new handle());
}
/**
* Conversion of GET-BUFFER-HANDLE() method (KW_GET_BUFH).
*
* Returns a handle of a particular buffer of a query object.
*
* @param bufferName
* buffer-name. A CHARACTER expression that evaluates to the name
* of a buffer in the query or DataSet object.
*
* @return Unknown buffer handle.
*/
public handle bufferHandle(character bufferName)
{
return (new handle());
}
/**
* Conversion of GET-BUFFER-HANDLE() method (KW_GET_BUFH).
*
* Returns a handle of a particular buffer of a query object.
*
* @param bufferSequenceNumber
* buffer-sequence-number. An INTEGER that represents the sequence
* number of the desired buffer.
*
* @return Unknown buffer handle.
*/
public handle bufferHandle(int bufferSequenceNumber)
{
return (new handle());
}
/**
* Conversion of GET-BUFFER-HANDLE() method (KW_GET_BUFH).
*
* Returns a handle of a particular buffer of a query object.
*
* @param bufferSequenceNumber
* buffer-sequence-number. An INTEGER that represents the sequence
* number of the desired buffer.
*
* @return Unknown buffer handle.
*/
@Override
public handle bufferHandle(int64 bufferSequenceNumber)
{
return (new handle());
}
/**
* Conversion of QUERY-CLOSE() method (KW_QRY_CLOS).
*
* Closes a query object.
*
* @return <code>false</code>.
*/
public logical queryClose()
{
return (logical.of(false));
}
/**
* Conversion of REPOSITION-BACKWARD() method (KW_REPOS_B).
*
* Moves a query object's result list pointer backward a particular number
* of rows.
*
* @return <code>false</code>.
*/
public logical queryBackward(int rows)
{
return (logical.of(false));
}
/**
* Conversion of REPOSITION-BACKWARD() method (KW_REPOS_B).
*
* Moves a query object's result list pointer backward a particular number
* of rows.
*
* @return <code>false</code>.
*/
public logical queryBackward(NumberType rows)
{
return (logical.of(false));
}
/**
* Conversion of REPOSITION-FORWARD() method (KW_REPOS_F).
*
* Moves a query object's result list pointer forward a particular number
* of rows.
*
* @return <code>false</code>.
*/
public logical queryForward(int rows)
{
return (logical.of(false));
}
/**
* Conversion of REPOSITION-FORWARD() method (KW_REPOS_F).
*
* Moves a query object's result list pointer forward a particular number
* of rows.
*
* @return <code>false</code>.
*/
public logical queryForward(NumberType rows)
{
return (logical.of(false));
}
/**
* 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>false</code>.
*/
public logical queryReposition(int n)
{
return (logical.of(false));
}
/**
* 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>false</code>.
*/
public logical queryReposition(NumberType n)
{
return (logical.of(false));
}
/**
* 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>false</code>.
*/
public logical queryRepositionByID(rowid id1, rowid...joinIDs)
{
return (logical.of(false));
}
/**
* 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>.
*/
@Override
public logical queryRepositionByID(rowid[] joinIDs)
{
return logical.FALSE;
}
/**
* 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>.
*/
public logical queryRepositionByID(character rowId)
{
return logical.of(false);
}
/**
* Conversion of NUM-RESULTS attribute (KW_NUM_RES).
*
* Getter of NUM-RESULTS attribute
*
* @return Unknown value.
*/
public integer getNumResults()
{
return (new integer());
}
/**
* Adds one new buffer to a query object or dynamic DataSet object,
* without affecting the other buffers, if any. Use the SET-BUFFERS( )
* method to remove all prior buffers and set all buffers for the object
* at the same time.
*
* @param bufHandle
* A buffer handle to add.
*
* @return <code>false</code>.
*/
public logical addBuffer(handle bufHandle)
{
return (logical.of(false));
}
/**
* Adds one new buffer to a query object or dynamic DataSet object,
* without affecting the other buffers, if any. Use the SET-BUFFERS( )
* method to remove all prior buffers and set all buffers for the object
* at the same time.
*
* @param buf
* A buffer to add.
*
* @return <code>false</code>.
*/
@Override
public logical addBuffer(Buffer buf)
{
return (logical.of(false));
}
/**
* Sets buffers for the query. Any buffers previously added
* or set are removed. Use the <code>addBuffer()</code> method to add one
* buffer to the object, without affecting the other buffers, if any.
* This method is the equivalent of <code>SET-BUFFERS()</code> method
* from 4GL.
*
* @param hBuffers
* Variable argument list of buffer handles to be set.
* In 4GL, the maximum number of buffers per query is 18.
*
* @return <code>false</code>.
*/
@Override
public logical setBuffers(handle... hBuffers)
{
return (logical.of(false));
}
/**
* Sets buffers for the query. Any buffers previously added
* or set are removed. Use the <code>addBuffer()</code> method to add one
* buffer to the object, without affecting the other buffers, if any.
* This method is the equivalent of <code>SET-BUFFERS()</code> method
* from 4GL.
*
* @param bufs
* Variable argument list of Buffer to be set.
* In 4GL, the maximum number of buffers per query is 18.
*
* @return true on success
*/
@Override
public logical setBuffers(Buffer... bufs)
{
return (logical.of(false));
}
/**
* 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 <code>false</code>.
*/
@Override
public logical prepare(String predicate)
{
return (logical.of(false));
}
/**
* 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 <code>false</code>.
*/
@Override
public logical prepare(character predicate)
{
return (logical.of(false));
}
/**
* 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
*/
@Override
public logical queryOpen()
{
return (logical.of(false));
}
/**
* Conversion of INDEX-INFORMATION attribute (KW_IDX_INFO).
*
* Getter of INDEX-INFORMATION attribute.
*
* @return Unknown value.
*/
public character indexInformation()
{
return (new character());
}
/**
* 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 Unknown value.
*/
public character indexInformation(int n)
{
return (new character());
}
/**
* 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 Unknown value.
*/
public character indexInformation(NumberType n)
{
return (new character());
}
/**
* Conversion of FORWARD-ONLY attribute (KW_FWD_ONLY).
*
* Getter of FORWARD-ONLY attribute.
*
* @return <code>false</code>.
*/
public logical forwardOnly()
{
return (logical.of(false));
}
/**
* Conversion of FORWARD-ONLY attribute (KW_FWD_ONLY).
*
* Setter of FORWARD-ONLY attribute.
*
* @param forwardOnly
* New value of FORWARD-ONLY attribute.
*/
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.
*/
public void changeForwardOnly(boolean forwardOnly)
{
}
/**
* Conversion of PREPARE_STRING attribute (KW_PREP_STR).
*
* Getter of PREPARE_STRING attribute.
*
* @return Unknown value.
*/
public character prepareString()
{
return (new character());
}
/**
* Getter for the CACHE attribute.
*
* @return See above.
*/
@Override
public integer getCache()
{
return new integer();
}
/**
* Setter for the CACHE attribute.
*
* @param n
* The cache value.
*/
@Override
public void setCache(integer n)
{
}
/**
* Setter for the CACHE attribute.
*
* @param n
* The cache value.
*/
@Override
public void setCache(long n)
{
}
/**
* Conversion of IS-OPEN attribute (KW_IS_OPEN).
*
* Getter of IS-OPEN attribute.
*
* @return current value of IS-OPEN attribute.
*/
public logical isOpen()
{
return (logical.of(false));
}
/**
* Conversion of GET-NEXT method (KW_GET_NEXT).
*
* Moves a query object's result list pointer ahead one row.
*
* @return <code>false</code>.
*/
@Override
public boolean _getNext()
{
return false;
}
/**
* Conversion of GET-NEXT method (KW_GET_NEXT).
*
* Moves a query object's result list pointer ahead one row.
*
* @param lockType
* Lock type.
*
* @return <code>false</code>.
*/
public logical getNext(LockType lockType)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> has not valid internal value.
*/
public logical getNext(long lock)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> has not valid internal value.
*/
public logical getNext(NumberType lock)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getNext(long lock, long nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getNext(long lock, NumberType nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getNext(NumberType lock, long nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getNext(NumberType lock, NumberType nowait)
{
return logical.of(false);
}
/**
* Conversion of GET-PREV method (KW_GET_PREV).
*
* Moves a query object's result list pointer back one row.
*
* @return <code>false</code>.
*/
public logical getPrevious()
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> has not valid internal value.
*/
public logical getPrevious(long lock)
{
return logical.of(false);
}
/**
* Conversion of GET-PREV method (KW_GET_PREV).
*
* Moves a query object's result list pointer back one row.
*
* @param lockType
* Lock type.
*
* @return <code>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> has not valid internal value.
*/
public logical getPrevious(LockType lockType)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> has not valid internal value.
*/
public logical getPrevious(NumberType lock)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getPrevious(long lock, long nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getPrevious(NumberType lock, long nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getPrevious(long lock, NumberType nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getPrevious(NumberType lock, NumberType nowait)
{
return logical.of(false);
}
/**
* Conversion of GET-FIRST method (KW_GET_1ST).
*
* Moves a query object's result list pointer to the first row.
*
* @return <code>false</code>.
*/
public logical getFirst()
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> has not valid internal value.
*/
public logical getFirst(long lock)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> has not valid internal value.
*/
public logical getFirst(NumberType lock)
{
return logical.of(false);
}
/**
* Conversion of GET-FIRST method (KW_GET_1ST).
*
* Moves a query object's result list pointer to the first row.
*
* @param lockType
* Lock type.
*
* @return <code>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> has not valid internal value.
*/
public logical getFirst(LockType lockType)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getFirst(long lock, long nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getFirst(NumberType lock, long nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getFirst(long lock, NumberType nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getFirst(NumberType lock, NumberType nowait)
{
return logical.of(false);
}
/**
* Conversion of GET-LAST method (KW_GET_LAST).
*
* Moves a query object's result list pointer to the last row.
*
* @return <code>false</code>.
*/
public logical getLast()
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> has not valid internal value.
*/
public logical getLast(long lock)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> has not valid internal value.
*/
public logical getLast(NumberType lock)
{
return logical.of(false);
}
/**
* Conversion of GET-LAST method (KW_GET_LAST).
*
* Moves a query object's result list pointer to the last row.
*
* @param lockType
* Lock type.
*
* @return <code>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> has not valid internal value.
*/
public logical getLast(LockType lockType)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getLast(long lock, long nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getLast(NumberType lock, long nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getLast(long lock, NumberType nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*
* @throws IllegalArgumentException
* if <code>lock</code> or <code>nowait</code> have not valid internal values.
*/
public logical getLast(NumberType lock, NumberType nowait)
{
return logical.of(false);
}
/**
* Conversion of GET-CURRENT() method (KW_GET_CUR).
*
* Refetches the current record or records associated with the query.
*
* @return <code>false</code>.
*/
public logical getCurrent()
{
return logical.of(false);
}
/**
* 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>false</code>.
*/
public logical getCurrent(long lock)
{
return logical.of(false);
}
/**
* 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>false</code>.
*/
public logical getCurrent(NumberType lock)
{
return logical.of(false);
}
/**
* Conversion of GET-CURRENT() method (KW_GET_CUR).
*
* Refetches the current record or records associated with the query.
*
* @param lockType
* Lock type.
*
* @return <code>false</code>.
*/
public logical getCurrent(LockType lockType)
{
return logical.of(false);
}
/**
* 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>false</code>.
*/
public logical getCurrent(long lock, long nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*/
public logical getCurrent(NumberType lock, long nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*/
public logical getCurrent(long lock, NumberType nowait)
{
return logical.of(false);
}
/**
* 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>false</code>.
*/
public logical getCurrent(NumberType lock, NumberType nowait)
{
return logical.of(false);
}
/**
* Conversion of NUM-BUFFERS() method (KW_NUM_BUFF).
*
* @return the number of buffers in a query or DataSet object.
*/
public integer numBuffers()
{
return new integer();
}
/**
* Setter for SKIP-DELETED-RECORD query attribute.
*
* @param on
* New value for the attribute.
*/
@Override
public void setSkipDeletedRecord(logical on)
{
// no-op
}
/**
* Get value of SKIP-DELETED-RECORD attribute of the query.
*
* @return the value of SKIP-DELETED-RECORD attribute of the query.
*/
@Override
public logical isSkipDeletedRecord()
{
return logical.of(true); // default value
}
/**
* No-op.
*
* @param dmo
* Not used.
* @param fields
* Not used.
*/
public void include(DataModelObject dmo, String ... fields)
{
}
/**
* No-op.
*
* @param dmo
* Not used.
* @param fields
* Not used.
*/
public void exclude(DataModelObject dmo, String ... fields)
{
}
/**
* No-op.
*
* @return <code>false</code>.
*/
public logical deleteResultListEntry()
{
return logical.of(false);
}
/**
* No-op.
*
* @return <code>false</code>.
*/
public logical deleteResultListEntry(boolean allowBetweenRows)
{
return logical.of(false);
}
/**
* No-op.
*
* @return <code>false</code>.
*/
@Override
public logical createResultListEntry()
{
return logical.of(false);
}
/**
* No-op.
*
* @param parameterFilter
* Not used.
*/
@Override
public void setParameterFilter(ParameterFilter parameterFilter)
{
}
/**
* No-op.
*/
@Override
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.
*/
@Override
public boolean addDynamicFilter(FieldReference fr, BaseDataType val, String format)
{
return false;
}
/**
* Clears any dynamically filters added at runtime. The query predicate will be restored to
* its form from generated at conversion time.
*/
@Override
public void clearDynamicFilters()
{
//no-op
}
@Override
public void setLenientOffEnd(boolean lenientOffEnd)
{
//no-op
}
/**
* 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.
*/
@Override
public void setIterating(boolean iterating)
{
//no-op
}
/**
* 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.
*/
@Override
public boolean isIterating()
{
return false;
}
/**
* Indicate whether the delegate query is of presort type.
*
* @return <code>true</code> if the query is of presort type.
*/
@Override
public boolean isPresort()
{
return false;
}
/**
* Indicate whether the delegate 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.
*/
@Override
public void setPresort(boolean presort)
{
//no-op
}
}
}