/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.translator; import java.util.Collection; import java.util.LinkedList; import java.util.List; import javax.resource.ResourceException; import javax.resource.cci.Connection; import javax.resource.cci.ConnectionFactory; import org.teiid.connector.DataPlugin; import org.teiid.core.TeiidException; import org.teiid.core.util.PropertiesUtils; import org.teiid.core.util.ReflectionHelper; import org.teiid.language.Argument; import org.teiid.language.BatchedUpdates; import org.teiid.language.Call; import org.teiid.language.Command; import org.teiid.language.LanguageFactory; import org.teiid.language.QueryExpression; import org.teiid.language.Select; import org.teiid.language.SetQuery; import org.teiid.logging.LogConstants; import org.teiid.logging.LogManager; import org.teiid.metadata.FunctionMethod; import org.teiid.metadata.FunctionParameter; import org.teiid.metadata.MetadataFactory; import org.teiid.metadata.RuntimeMetadata; import org.teiid.translator.CacheDirective.Scope; import org.teiid.translator.TypeFacility.RUNTIME_CODES; import org.teiid.translator.TypeFacility.RUNTIME_NAMES; /** * <p>The primary entry point for a Translator. This class should be extended by the custom translator writer.</p> * * The deployer instantiates this class through reflection. So it is important to have no-arg constructor. Once constructed * the "start" method is called. This class represents the basic capabilities of the translator. */ public class ExecutionFactory<F, C> { public enum TransactionSupport { XA, LOCAL, NONE } public enum SupportedJoinCriteria { /** * Indicates that any supported criteria is allowed. */ ANY, /** * Indicates that any simple comparison of elements is allowed. */ THETA, /** * Indicates that only equality predicates of elements are allowed. */ EQUI, /** * Indicates that only equality predicates between * exactly one primary and foreign key is allowed per join. */ KEY } public enum NullOrder { HIGH, LOW, FIRST, LAST, UNKNOWN } public static final int DEFAULT_MAX_FROM_GROUPS = -1; public static final int DEFAULT_MAX_IN_CRITERIA_SIZE = -1; private static final TypeFacility TYPE_FACILITY = new TypeFacility(); /* * Managed execution properties */ private boolean immutable; private boolean sourceRequired = true; private Boolean sourceRequiredForMetadata; private boolean threadBound; /* * Support properties */ private boolean supportsSelectDistinct; private boolean supportsOuterJoins; private SupportedJoinCriteria supportedJoinCriteria = SupportedJoinCriteria.ANY; private boolean supportsOrderBy; private boolean supportsInnerJoins; private boolean supportsFullOuterJoins; private boolean requiresCriteria; private int maxInSize = DEFAULT_MAX_IN_CRITERIA_SIZE; private int maxDependentInPredicates = DEFAULT_MAX_IN_CRITERIA_SIZE; private boolean copyLobs; private boolean supportsNativeQueries; private LinkedList<FunctionMethod> pushdownFunctionMethods = new LinkedList<FunctionMethod>(); private String nativeProcedureName = "native"; //$NON-NLS-1$ private String collationLocale; private TransactionSupport transactionSupport = TransactionSupport.XA; private String excludedCommonTableExpressionName; /** * Initialize the connector with supplied configuration */ public void start() throws TranslatorException { if (!isSourceRequiredForCapabilities()) { initCapabilities(null); } } /** * Defines if the Connector is read-only connector * @return */ @TranslatorProperty(display="Is Immutable",description="Is Immutable, True if the source never changes.",advanced=true) public boolean isImmutable() { return immutable; } public void setImmutable(boolean arg0) { this.immutable = arg0; } @TranslatorProperty(display="Copy LOBs",description="If true, returned LOBs will be copied, rather than streamed from the source",advanced=true) public boolean isCopyLobs() { return copyLobs; } public void setCopyLobs(boolean copyLobs) { this.copyLobs = copyLobs; } /** * Return a connection object from the given connection factory. * * The default implementation assumes a JCA {@link ConnectionFactory}. Subclasses should override, if they use * another type of connection factory. * * @deprecated * @see #getConnection(Object, ExecutionContext) * @param factory * @return a connection * @throws TranslatorException */ @Deprecated @SuppressWarnings("unchecked") public C getConnection(F factory) throws TranslatorException { if (factory == null) { return null; } if (factory instanceof ConnectionFactory) { try { return (C) ((ConnectionFactory)factory).getConnection(); } catch (ResourceException e) { throw new TranslatorException(DataPlugin.Event.TEIID60000, e); } } throw new AssertionError(factory.getClass().getName() + " is was not a ConnectionFactory implementation"); //$NON-NLS-1$ } /** * Return a connection object from the given connection factory. * * The default implementation assumes a JCA {@link ConnectionFactory}. Subclasses should override, if they use * another type of connection factory or wish to use the {@link ExecutionContext}. By default calls {@link #getConnection(Object)} * * @param factory * @param executionContext null if this is a system request for a connection * @return a connection * @throws TranslatorException */ public C getConnection(F factory, ExecutionContext executionContext) throws TranslatorException { return getConnection(factory); } /** * Closes a connection object from the given connection factory. * * The default implementation assumes a JCA {@link Connection}. Subclasses should override, if they use * another type of connection. * * @param connection * @param factory */ public void closeConnection(C connection, F factory) { if (connection == null) { return; } if (connection instanceof Connection) { try { ((Connection)connection).close(); } catch (ResourceException e) { LogManager.logDetail(LogConstants.CTX_CONNECTOR, e, "Error closing"); //$NON-NLS-1$ } return; } throw new AssertionError("A connection was created, but no implementation provided for closeConnection"); //$NON-NLS-1$ } /** * Flag that indicates if a underlying source connection required for this execution factory to work * @return */ public boolean isSourceRequired() { return sourceRequired; } public void setSourceRequired(boolean value) { this.sourceRequired = value; } /** * Flag that indicates if a underlying source connection required for this execution factory to return metadata * @return true if required */ public boolean isSourceRequiredForMetadata() { if (sourceRequiredForMetadata == null) { //matches pre 8.1 behavior return sourceRequired; } //TODO we could also consider making this an annotation of the getMetadata call return sourceRequiredForMetadata; } /** * If true, the {@link #initCapabilities(Object)} method will be consulted prior * to determining the capabilities * @return */ public boolean isSourceRequiredForCapabilities() { return false; } /** * Will be called by {@link #start()} with a null connection if a source connection is not {@link #isSourceRequiredForCapabilities()} * @param connection * @throws TranslatorException */ public void initCapabilities(C connection) throws TranslatorException { } public void setSourceRequiredForMetadata(boolean sourceRequiredForMetadata) { this.sourceRequiredForMetadata = sourceRequiredForMetadata; } /** * Obtain a reference to the default LanguageFactory that can be used to construct * new language interface objects. This is typically needed when modifying the language * objects passed to the connector or for testing when objects need to be created. */ public LanguageFactory getLanguageFactory() { return LanguageFactory.INSTANCE; } /** * Obtain a reference to the type facility, which can be used to perform many type * conversions supplied by the Connector API. */ public TypeFacility getTypeFacility() { return TYPE_FACILITY; } /** * Create an execution object for the specified command * @param command the command * @param executionContext Provides information about the context that this command is * executing within, such as the identifiers for the command being executed * @param metadata Access to runtime metadata if needed to translate the command * @param connection connection factory object to the data source * @return An execution object that can use to execute the command */ public Execution createExecution(Command command, ExecutionContext executionContext, RuntimeMetadata metadata, C connection) throws TranslatorException { if (command instanceof Call) { Call obj = (Call)command; //TODO: our extension property support in designer makes ad-hoc properties impossible, so //we just match based upon name. it would be better to have the metadatarepository/tooling add a teiid property //to explicitly set this proc as direct. //the other approach would be to addd a native system stored procedure, but that would require //special security semantics, whereas this proc can be secured on a schema basis if (supportsDirectQueryProcedure() && obj.getMetadataObject().getName().equals(getDirectQueryProcedureName())) { List<Argument> arguments = obj.getArguments(); return createDirectExecution(arguments, command, executionContext, metadata, connection); } } if (command instanceof QueryExpression) { return createResultSetExecution((QueryExpression)command, executionContext, metadata, connection); } if (command instanceof Call) { return createProcedureExecution((Call)command, executionContext, metadata, connection); } return createUpdateExecution(command, executionContext, metadata, connection); } @SuppressWarnings("unused") public ResultSetExecution createResultSetExecution(QueryExpression command, ExecutionContext executionContext, RuntimeMetadata metadata, C connection) throws TranslatorException { throw new TranslatorException(DataPlugin.Event.TEIID60001, DataPlugin.Util.gs(DataPlugin.Event.TEIID60001, "createResultSetExecution")); //$NON-NLS-1$ } @SuppressWarnings("unused") public ProcedureExecution createProcedureExecution(Call command, ExecutionContext executionContext, RuntimeMetadata metadata, C connection) throws TranslatorException { throw new TranslatorException(DataPlugin.Event.TEIID60001, DataPlugin.Util.gs(DataPlugin.Event.TEIID60001, "createProcedureExecution")); //$NON-NLS-1$ } @SuppressWarnings("unused") public UpdateExecution createUpdateExecution(Command command, ExecutionContext executionContext, RuntimeMetadata metadata, C connection) throws TranslatorException { throw new TranslatorException(DataPlugin.Event.TEIID60001, DataPlugin.Util.gs(DataPlugin.Event.TEIID60001, "createUpdateExecution")); //$NON-NLS-1$ } @SuppressWarnings("unused") public ProcedureExecution createDirectExecution(List<Argument> arguments, Command command, ExecutionContext executionContext, RuntimeMetadata metadata, C connection) throws TranslatorException { throw new TranslatorException(DataPlugin.Event.TEIID60001, DataPlugin.Util.gs(DataPlugin.Event.TEIID60001, "createDirectExecution")); //$NON-NLS-1$ } /** * Get a MetadataProcessor for the translator to read the metadata. Typically this will return a new instance. * @return */ public MetadataProcessor<C> getMetadataProcessor() { return null; } /** * Support indicates connector can accept queries with SELECT DISTINCT * @since 3.1 SP2 */ @TranslatorProperty(display="Supports Select Distinct", description="True, if this connector supports SELECT DISTINCT", advanced=true) public boolean supportsSelectDistinct() { return supportsSelectDistinct; } public void setSupportsSelectDistinct(boolean supportsSelectDistinct) { this.supportsSelectDistinct = supportsSelectDistinct; } /** * Support indicates connector can accept expressions other than element * symbols in the SELECT clause. Specific supports for the expression * type are still checked. * @since 6.1.0 */ public boolean supportsSelectExpression() { return false; } /** * Support indicates connector can accept groups with aliases * @since 3.1 SP2 */ public boolean supportsAliasedTable() { return false; } /** * Get the supported join criteria. A null return value will be treated * as {@link SupportedJoinCriteria#ANY} * @since 6.1.0 */ @TranslatorProperty(display="Supported Join Criteria", description="Returns one of any, theta, equi, or key", advanced=true) public SupportedJoinCriteria getSupportedJoinCriteria() { return supportedJoinCriteria; } public void setSupportedJoinCriteria( SupportedJoinCriteria supportedJoinCriteria) { this.supportedJoinCriteria = supportedJoinCriteria; } /** * Support indicates connector can accept inner or cross joins * @since 6.1.0 */ @TranslatorProperty(display="Supports Inner Joins", description="True, if this connector supports inner joins", advanced=true) public boolean supportsInnerJoins() { return supportsInnerJoins; } public void setSupportsInnerJoins(boolean supportsInnerJoins) { this.supportsInnerJoins = supportsInnerJoins; } /** * Support indicates connector can accept self-joins where a * group is joined to itself with aliases. Connector must also support * {@link #supportsAliasedTable()}. * @since 3.1 SP2 */ public boolean supportsSelfJoins() { return false; } /** * Support indicates connector can accept left outer joins * @since 3.1 SP2 */ @TranslatorProperty(display="Supports Outer Joins", description="True, if this connector supports outer joins", advanced=true) public boolean supportsOuterJoins() { return supportsOuterJoins; } public void setSupportsOuterJoins(boolean supportsOuterJoins) { this.supportsOuterJoins = supportsOuterJoins; } /** * Support indicates connector can accept full outer joins * @since 3.1 SP2 */ @TranslatorProperty(display="Supports Full Outer Joins", description="True, if this connector supports full outer joins", advanced=true) public boolean supportsFullOuterJoins() { return supportsFullOuterJoins; } public void setSupportsFullOuterJoins(boolean supportsFullOuterJoins) { this.supportsFullOuterJoins = supportsFullOuterJoins; } /** * Support indicates connector can accept inline views (subqueries * in the FROM clause). * @since 4.1 */ public boolean supportsInlineViews() { return false; } /** * Support indicates connector accepts criteria of form (element = constant) * @since 3.1 SP2 */ public boolean supportsCompareCriteriaEquals() { return false; } /** * Support indicates connector accepts criteria of form (element <=|>= constant) * <br>The query engine will may pushdown queries containing < or > if NOT is also * supported. * @since 3.1 SP2 */ public boolean supportsCompareCriteriaOrdered() { return false; } /** * Support indicates connector accepts criteria of form (element <|> constant) */ public boolean supportsCompareCriteriaOrderedExclusive() { return supportsCompareCriteriaOrdered(); } /** * Support indicates connector accepts criteria of form (element LIKE constant) * @since 3.1 SP2 */ public boolean supportsLikeCriteria() { return false; } /** * Support indicates connector accepts criteria of form (element LIKE constant ESCAPE char) * @since 3.1 SP2 */ public boolean supportsLikeCriteriaEscapeCharacter() { return false; } /** * Support indicates connector accepts criteria of form (element IN set) * @since 3.1 SP2 */ public boolean supportsInCriteria() { return false; } /** * Support indicates connector accepts IN criteria with a subquery on the right side * @since 4.0 */ public boolean supportsInCriteriaSubquery() { return false; } /** * Support indicates connector accepts criteria of form (element IS NULL) * @since 3.1 SP2 */ public boolean supportsIsNullCriteria() { return false; } /** * Support indicates connector accepts logical criteria connected by OR * @since 3.1 SP2 */ public boolean supportsOrCriteria() { return false; } /** * Support indicates connector accepts logical criteria NOT * @since 3.1 SP2 */ public boolean supportsNotCriteria() { return false; } /** * Support indicates connector accepts the EXISTS criteria * @since 4.0 */ public boolean supportsExistsCriteria() { return false; } /** * Support indicates connector accepts the quantified comparison criteria that * use SOME * @since 4.0 */ public boolean supportsQuantifiedCompareCriteriaSome() { return false; } /** * Support indicates connector accepts the quantified comparison criteria that * use ALL * @since 4.0 */ public boolean supportsQuantifiedCompareCriteriaAll() { return false; } /** * Support indicates connector accepts ORDER BY clause, including multiple elements * and ascending and descending sorts. * @since 3.1 SP2 */ @TranslatorProperty(display="Supports ORDER BY", description="True, if this connector supports ORDER BY", advanced=true) public boolean supportsOrderBy() { return supportsOrderBy; } public void setSupportsOrderBy(boolean supportsOrderBy) { this.supportsOrderBy = supportsOrderBy; } /** * Indicates the collation used for sorting */ @TranslatorProperty(display="Collation Locale", description="The collation locale used by default for sorting.", advanced=true) public String getCollationLocale() { return collationLocale; } public void setCollationLocale(String collation) { this.collationLocale = collation; } /** * Support indicates connector accepts ORDER BY clause with columns not from the select * @since 6.2 * @return */ public boolean supportsOrderByUnrelated() { return false; } /** * Returns the default null ordering * @since 7.1 * @return the {@link NullOrder} */ public NullOrder getDefaultNullOrder() { return NullOrder.UNKNOWN; } /** * Returns whether the database supports explicit null ordering. * @since 7.1 * @return true if nulls first/last can be specified */ public boolean supportsOrderByNullOrdering() { return false; } /** * Whether the source supports an explicit GROUP BY clause * @since 6.1 */ public boolean supportsGroupBy() { return false; } /** * Whether the source supports grouping only over a single table * @return */ public boolean supportsOnlySingleTableGroupBy() { return false; } /** * Whether the source supports grouping with multiple distinct aggregates * @return */ public boolean supportsGroupByMultipleDistinctAggregates() { return supportsGroupBy(); } /** * Whether the source supports the HAVING clause * @since 6.1 */ public boolean supportsHaving() { return false; } /** * Support indicates connector can accept the SUM aggregate function * @since 3.1 SP2 */ public boolean supportsAggregatesSum() { return false; } /** * Support indicates connector can accept the AVG aggregate function * @since 3.1 SP2 */ public boolean supportsAggregatesAvg() { return false; } /** * Support indicates connector can accept the MIN aggregate function * @since 3.1 SP2 */ public boolean supportsAggregatesMin() { return false; } /** * Support indicates connector can accept the MAX aggregate function * @since 3.1 SP2 */ public boolean supportsAggregatesMax() { return false; } /** * Support indicates connector can accept the COUNT aggregate function * @since 3.1 SP2 */ public boolean supportsAggregatesCount() { return false; } /** * Support indicates connector can accept the COUNT(*) aggregate function * @since 3.1 SP2 */ public boolean supportsAggregatesCountStar() { return false; } /** * Support indicates connector can accept DISTINCT within aggregate functions * @since 3.1 SP2 */ public boolean supportsAggregatesDistinct() { return false; } /** * Support indicates connector can accept STDDEV_POP, STDDEV_VAR, VAR_POP, VAR_SAMP * @since 7.1 */ public boolean supportsAggregatesEnhancedNumeric() { return false; } /** * @return true if string_agg is supported * @since 8.4 */ public boolean supportsStringAgg() { return false; } /** * Support indicates connector can accept scalar subqueries in the SELECT, WHERE, and * HAVING clauses * @since 4.0 */ public boolean supportsScalarSubqueries() { return false; } /** * Support indicates connector can accept correlated subqueries wherever subqueries * are accepted * @since 4.0 */ public boolean supportsCorrelatedSubqueries() { return false; } /** * Support indicates connector can accept queries with searched CASE WHEN <criteria> ... END * @since 4.0 */ public boolean supportsSearchedCaseExpressions() { return false; } /** * Support indicates that the connector supports the UNION of two queries. * @since 4.2 */ public boolean supportsUnions() { return false; } /** * Support indicates that the connector supports an ORDER BY on a SetQuery. * @since 5.6 */ public boolean supportsSetQueryOrderBy() { return false; } /** * Support indicates that the connector supports the INTERSECT of two queries. * @since 5.6 */ public boolean supportsIntersect() { return false; } /** * Support indicates that the connector supports the EXCEPT of two queries. * @since 5.6 */ public boolean supportsExcept() { return false; } /** * Get list of all supported function names. Arithmetic functions have names like * "+". * @see SourceSystemFunctions for a listing of system pushdown functions. Note that * not all system functions are listed as some functions will use a common name * such as CONCAT vs. the || operator, and other functions will be rewritten and * not pushed down, such as SPACE. * <br><b>Note:</b> User defined functions should be specified fully qualified. * @since 3.1 SP3 */ public List<String> getSupportedFunctions() { return null; } /** * Get a list of {@link FunctionMethod}s that will be contributed to the SYS schema. * To avoid conflicts with system functions, the function name should contain a * qualifier - typically <translator name>.<function name> * @see ExecutionFactory#addPushDownFunction(String, String, FunctionParameter, FunctionParameter...) * @return */ public List<FunctionMethod> getPushDownFunctions(){ return pushdownFunctionMethods; } /** * Adds a pushdown function. * @param qualifier will be pre-pended to the name * @param name * @param returnType see {@link RUNTIME_NAMES} for type names * @param paramTypes see {@link RUNTIME_NAMES} for type names * @return the FunctionMethod created. */ protected FunctionMethod addPushDownFunction(String qualifier, String name, String returnType, String...paramTypes) { FunctionMethod method = FunctionMethod.createFunctionMethod(qualifier + '.' + name, name, qualifier, returnType, paramTypes); method.setNameInSource(name); pushdownFunctionMethods.add(method); return method; } /** * Get the integer value representing the number of values allowed in an IN criteria * in the WHERE clause of a query * @since 5.0 */ @TranslatorProperty(display="Max number of IN predicate entries", advanced=true) public int getMaxInCriteriaSize() { return maxInSize; } public void setMaxInCriteriaSize(int maxInSize) { this.maxInSize = maxInSize; } /** * Get the integer value representing the max number of dependent IN predicates. * This may be used to split a single dependent value via OR, or multiple dependent values * via AND. */ @TranslatorProperty(display="Max number of dependent IN predicates", advanced=true) public int getMaxDependentInPredicates() { return maxDependentInPredicates; } public void setMaxDependentInPredicates(int maxDependentInPredicates) { this.maxDependentInPredicates = maxDependentInPredicates; } /** * <p>Support indicates that the connector supports non-column expressions in GROUP BY, such as: * <code>SELECT dayofmonth(theDate), COUNT(*) FROM table GROUP BY dayofmonth(theDate)</code></p> * @since 5.0 */ public boolean supportsFunctionsInGroupBy() { return false; } /** * Gets whether the connector can limit the number of rows returned by a query. * @since 5.0 SP1 */ public boolean supportsRowLimit() { return false; } /** * Gets whether the connector supports a SQL clause (similar to the LIMIT with an offset) that can return * result sets that start in the middle of the resulting rows returned by a query * @since 5.0 SP1 */ public boolean supportsRowOffset() { return false; } /** * The number of groups supported in the from clause. Added for a Sybase limitation. * @since 5.6 * @return the number of groups supported in the from clause, or -1 if there is no limit */ public int getMaxFromGroups() { return DEFAULT_MAX_FROM_GROUPS; } /** * Whether the source prefers to use ANSI style joins. * @since 6.0 */ public boolean useAnsiJoin() { return false; } /** * Whether the source supports queries without criteria. * @since 6.0 */ @TranslatorProperty(display="Requries Criteria", description="True, if this connector requires criteria on source queries", advanced=true) public boolean requiresCriteria() { return requiresCriteria; } public void setRequiresCriteria(boolean requiresCriteria) { this.requiresCriteria = requiresCriteria; } /** * Whether the source supports {@link BatchedUpdates} * @since 6.0 */ public boolean supportsBatchedUpdates() { return false; } /** * Whether the source supports updates with multiple value sets * @since 6.0 */ public boolean supportsBulkUpdate() { return false; } /** * Support indicates that the connector can accept INSERTs with * values specified by a {@link SetQuery} or {@link Select} * @since 6.1 */ public boolean supportsInsertWithQueryExpression() { return false; } public static <T> T getInstance(Class<T> expectedType, String className, Collection<?> ctorObjs, Class<? extends T> defaultClass) throws TranslatorException { try { if (className == null) { if (defaultClass == null) { throw new TranslatorException(DataPlugin.Event.TEIID60004, DataPlugin.Util.gs(DataPlugin.Event.TEIID60004)); } return expectedType.cast(defaultClass.newInstance()); } return expectedType.cast(ReflectionHelper.create(className, ctorObjs, Thread.currentThread().getContextClassLoader())); } catch (TeiidException e) { throw new TranslatorException(DataPlugin.Event.TEIID60005, e); } catch (IllegalAccessException e) { throw new TranslatorException(DataPlugin.Event.TEIID60005, e); } catch(InstantiationException e) { throw new TranslatorException(DataPlugin.Event.TEIID60005, e); } } /** * Implement to provide metadata to the metadata for use by the engine. This is the * primary method of creating metadata for dynamic VDBs. * @param metadataFactory * @param conn may be null if the source is not required * @throws TranslatorException to indicate a recoverable error, otherwise a RuntimeException * @see #isSourceRequiredForMetadata() */ public void getMetadata(MetadataFactory metadataFactory, C conn) throws TranslatorException { MetadataProcessor mp = getMetadataProcessor(); if (mp != null) { PropertiesUtils.setBeanProperties(mp, metadataFactory.getModelProperties(), "importer"); //$NON-NLS-1$ mp.process(metadataFactory, conn); } } /** * Indicates if LOBs are usable after the execution is closed. * @return true if LOBs can be used after close * @since 7.2 */ public boolean areLobsUsableAfterClose() { return false; } /** * @return true if the WITH clause is supported * @since 7.2 */ public boolean supportsCommonTableExpressions() { return false; } /** * @return true if a recursive WITH clause item is supported * @since 8.9 */ public boolean supportsRecursiveCommonTableExpressions() { return false; } /** * @return true if the WITH clause can appear in subqueries * @since 8.12 */ public boolean supportsSubqueryCommonTableExpressions() { return supportsCommonTableExpressions(); } /** * @return true if a correlated subquery can support a limit clause * @since 8.12 */ public boolean supportsCorrelatedSubqueryLimit() { return supportsCorrelatedSubqueries(); } /** * @return true if Advanced OLAP operations are supported * including the aggregate function filter clause. * @since 7.5 */ public boolean supportsAdvancedOlapOperations() { return false; } /** * @return true if Elementary OLAP operations are supported * including window functions and inline window specifications that include * simple expressions in partitioning and ordering * @since 7.5 */ public boolean supportsElementaryOlapOperations() { return false; } /** * @return true if all aggregates can have window function order by clauses. * @since 7.5 */ public boolean supportsWindowOrderByWithAggregates() { return supportsElementaryOlapOperations(); } /** * @return true if distinct aggregates can be windowed function. * @since 7.6 */ public boolean supportsWindowDistinctAggregates() { return supportsElementaryOlapOperations(); } /** * @return true if array_agg is supported * @since 7.5 */ public boolean supportsArrayAgg() { return false; } /** * @return true if the SIMILAR TO predicate is supported * @since 7.5 */ public boolean supportsSimilarTo() { return false; } /** * @return true if the LIKE_REGEX predicate is supported * @since 7.4 */ public boolean supportsLikeRegex() { return false; } /** * Used for fine grained control of convert/cast pushdown. The {@link #getSupportedFunctions()} should * contain {@link SourceSystemFunctions#CONVERT}. This method can then return false to indicate * a lack of specific support. The engine will does not care about an unnecessary conversion * where fromType == toType. * * By default lob conversion is disabled. * * @param fromType @see RUNTIME_CODES * @param toType @see RUNTIME_CODES * @return true if the given conversion is supported. * @since 8.0 */ public boolean supportsConvert(int fromType, int toType) { if (fromType == RUNTIME_CODES.OBJECT || fromType == RUNTIME_CODES.CLOB || fromType == RUNTIME_CODES.XML || fromType == RUNTIME_CODES.BLOB || toType == RUNTIME_CODES.CLOB || toType == RUNTIME_CODES.XML || toType == RUNTIME_CODES.BLOB) { return false; } return true; } /** * @return true if only Literal comparisons (equality, ordered, like, etc.) are supported for non-join conditions. * @since 8.0 */ public boolean supportsOnlyLiteralComparison() { return false; } /** * NOTE: The pushed independent tuples will not have been * converted to a unique set and may contain duplicates. * @return true if dependent join key pushdown is supported * @since 8.0 */ public boolean supportsDependentJoins() { return false; } /** * @return true if full dependent join pushdown is supported * @since 8.5 * @return */ public boolean supportsFullDependentJoins() { return false; } public enum Format { NUMBER, DATE } /** * See also {@link #supportsFormatLiteral(String, Format)} * @return true if only literal formats are supports. */ public boolean supportsOnlyFormatLiterals() { return false; } /** * * @param literal * @param format * @return true if the given Java format string is supported */ public boolean supportsFormatLiteral(String literal, Format format) { return false; } /** * Refines subquery support. * @return true if subqueries are supported in the on clause. */ public boolean supportsSubqueryInOn() { return true; } /** * Get the {@link CacheDirective} to control command caching. * <p>Use {@link Scope#NONE} to indicate to the engine that no caching should be performed by the engine.</p> * <p>If cache parameters on the {@link CacheDirective} will be changed by the {@link Execution}, then * a new instance of a {@link CacheDirective} should be set each time.</p> * @param command * @param executionContext * @param metadata * @throws TranslatorException */ public CacheDirective getCacheDirective(Command command, ExecutionContext executionContext, RuntimeMetadata metadata) throws TranslatorException { return null; } /** * When forkable the engine may use a separate thread to interact with returned {@link Execution}. * @return true if {@link Execution}s can be called in separate threads from the processing thread */ public boolean isForkable() { return true; } /** * @return True, if this translator's executions must complete in a single thread. */ @TranslatorProperty(display="Thread Bound", description="True, if this translator's executions must complete in a single thread.", advanced=true) public boolean isThreadBound() { return threadBound; } /** * The engine uses array types for dependent joins and for array expression. * @return true if an array type is supported. */ public boolean supportsArrayType() { return false; } /** * @return true if array type expressions can be projected */ public boolean supportsSelectExpressionArrayType() { return supportsArrayType(); } /** * True, if this translator supports execution of source specific commands unaltered through a direct procedure. * @deprecated * @see #supportsDirectQueryProcedure() * @return */ @Deprecated @TranslatorProperty(display="Deprecated Property:Supports Direct Query Procedure", description="Deprecated Property, Use Supports Direct Query Procedure instead", advanced=true) final public boolean supportsNativeQueries() { return this.supportsNativeQueries; } /** * @deprecated * @see #setSupportsDirectQueryProcedure(boolean) */ @Deprecated final public void setSupportsNativeQueries(boolean state) { this.supportsNativeQueries = state; } /** * True, if this translator supports execution of source specific commands unaltered through a direct procedure. * @return */ @TranslatorProperty(display="Supports Direct Query Procedure", description="True, if this translator supports execution of source specific commands unaltered through a direct procedure", advanced=true) public boolean supportsDirectQueryProcedure() { return this.supportsNativeQueries; } public void setSupportsDirectQueryProcedure(boolean state) { this.supportsNativeQueries = state; } /** * Defines the name of the direct processing procedure. This metadata or signature * of the procedure is defined automatically. * @deprecated * @see #getDirectQueryProcedureName() * @return */ @Deprecated @TranslatorProperty(display="Deprecated Property:Direct Query Procedure Name", description="Deprecated Property, use Direct Query Procedure Name", advanced=true) final public String getNativeQueryProcedureName() { return this.nativeProcedureName; } /** * @deprecated * @see #setDirectQueryProcedureName(String) */ @Deprecated final public void setNativeQueryProcedureName(String name) { this.nativeProcedureName = name; } /** * Defines the name of the direct processing procedure. This metadata or signature * of the procedure is defined automatically. * @return */ @TranslatorProperty(display="Direct Query Procedure Name", description="The name of the direct query procedure", advanced=true) public String getDirectQueryProcedureName() { return this.nativeProcedureName; } public void setDirectQueryProcedureName(String name) { this.nativeProcedureName = name; } /** * @return true if only correlated subqueries are supported. */ public boolean supportsOnlyCorrelatedSubqueries() { return false; } /** * @return true if the translator support SELECT without a FROM clause */ public boolean supportsSelectWithoutFrom() { return false; } /** * @return true if the translator support GROUP BY ROLLUP */ public boolean supportsGroupByRollup() { return false; } /** * @return true if order by is supported over a grouping with a rollup, cube, etc. */ public boolean supportsOrderByWithExtendedGrouping() { return supportsOrderBy(); } public void setThreadBound(boolean threadBound) { this.threadBound = threadBound; } /** * True if the only a single value is returned for the update count. * This overrides the default expectation of a update count array * for bulk/batch commands. It is expected that every command * is successful. * @return */ public boolean returnsSingleUpdateCount() { return false; } /** * Return true if the source has columns marked with the teiid_rel:partial that * can return more rows than specified by a filter if the column is also projected. * This most closely matches the semantics of ldap queries with multi-valued * attributes marked as partial. * <br>When true, the following supports cannot also be true: * <ul> * <li>supportsOuterJoins() * <li>supportsFullOuterJoins() * <li>supportsInlineViews() * <li>supportsIntersect() * <li>supportsExcept() * <li>supportsSelectExpression() * <li>supportsUnions() * <li>supportsSelectDistinct() * <li>supportsGroupBy() * </ul> * @return */ public boolean supportsPartialFiltering() { return false; } /** * If dependent join predicates should use literals that are marked as bind eligible. */ public boolean useBindingsForDependentJoin() { return true; } /** * The required escape character or null if all are supported. * @return */ public Character getRequiredLikeEscape() { return null; } /** * If a scalar subquery can be projected. * @return */ public boolean supportsScalarSubqueryProjection() { return supportsScalarSubqueries(); } @TranslatorProperty(display="Transaction Support", description="The level of transaction support. Used by the engine to determine if a transaction is needed for autoCommit mode.", advanced=true) public TransactionSupport getTransactionSupport() { return transactionSupport; } public void setTransactionSupport(TransactionSupport transactionSupport) { this.transactionSupport = transactionSupport; } @TranslatorProperty(display="Excluded Common Table Expression Name", description="Set if the source won't support the given common table expression name.", advanced=true) public String getExcludedCommonTableExpressionName() { return excludedCommonTableExpressionName; } public void setExcludedCommonTableExpressionName( String excludedCommonTableExpressionName) { this.excludedCommonTableExpressionName = excludedCommonTableExpressionName; } /** * * @return true if the source supports lateral join */ public boolean supportsLateralJoin() { return false; } /** * * @return true if the source supports lateral join conditions */ public boolean supportsLateralJoinCondition() { return supportsLateralJoin(); } /** * * @return */ public boolean supportsProcedureTable() { return false; } /** * @return true if the source supports upsert */ public boolean supportsUpsert() { return false; } }