Repository: metamodel Updated Branches: refs/heads/master 49333c662 -> b417bc9c5
METAMODEL-188: Fixed Fixes #47 Project: http://git-wip-us.apache.org/repos/asf/metamodel/repo Commit: http://git-wip-us.apache.org/repos/asf/metamodel/commit/b417bc9c Tree: http://git-wip-us.apache.org/repos/asf/metamodel/tree/b417bc9c Diff: http://git-wip-us.apache.org/repos/asf/metamodel/diff/b417bc9c Branch: refs/heads/master Commit: b417bc9c5148bca27c14688638c3e6aa9e50a50a Parents: 49333c6 Author: Kasper Sørensen <[email protected]> Authored: Fri Sep 11 16:56:36 2015 +0200 Committer: Kasper Sørensen <[email protected]> Committed: Fri Sep 11 16:56:36 2015 +0200 ---------------------------------------------------------------------- CHANGES.md | 1 + .../metamodel/QueryPostprocessDataContext.java | 6 +- .../org/apache/metamodel/query/FilterItem.java | 32 +-- .../apache/metamodel/query/OperatorType.java | 53 +--- .../metamodel/query/OperatorTypeImpl.java | 114 ++++++++ .../java/org/apache/metamodel/query/Query.java | 2 +- .../LegacyDeserializationObjectInputStream.java | 286 ++++++++++--------- .../metamodel/query/OperatorTypeTest.java | 45 ++- .../apache/metamodel/util/FormatHelperTest.java | 1 - .../elasticsearch/ElasticSearchDataContext.java | 26 +- .../ElasticSearchDataContextTest.java | 2 +- .../org/apache/metamodel/jdbc/JdbcUtils.java | 2 +- .../jdbc/dialects/AbstractQueryRewriter.java | 2 +- .../jdbc/dialects/DB2QueryRewriter.java | 21 +- .../jdbc/dialects/DefaultQueryRewriter.java | 2 +- .../metamodel/mongodb/MongoDbDataContext.java | 61 ++-- .../salesforce/SalesforceDataContext.java | 2 +- .../salesforce/SalesforceUpdateCallback.java | 2 +- 18 files changed, 376 insertions(+), 284 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/CHANGES.md ---------------------------------------------------------------------- diff --git a/CHANGES.md b/CHANGES.md index 89baa1b..e42adad 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,7 @@ * [METAMODEL-176] - Trimmed the transient dependencies of the JDBC module. * [METAMODEL-170] - Dropped support for Java 6. * [METAMODEL-178] - Added AggregateFunction and ScalarFunction interfaces. Changed FunctionType enum to be super-interface of those. Compatibility is retained but a recompile of code using FunctionType is needed. + * [METAMODEL-188] - Changed OperatorType enum to be an interface. Compatibility is retained but a recompile of code is needed. * [METAMODEL-179] - Ensured that HdfsResource is not closing a shared HDFS file system reference. * [METAMODEL-171] - Made integration tests for Cassandra module function properly in all environments. * [METAMODEL-177] - Fixed a bug pertaining to the serializability of HdfsResource. http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java b/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java index 1fecf98..0282a26 100644 --- a/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java +++ b/core/src/main/java/org/apache/metamodel/QueryPostprocessDataContext.java @@ -142,7 +142,7 @@ public abstract class QueryPostprocessDataContext extends AbstractDataContext im final SelectItem selectItem = whereItem.getSelectItem(); if (!whereItem.isCompoundFilter() && selectItem != null && selectItem.getColumn() != null) { final Column column = selectItem.getColumn(); - if (column.isPrimaryKey() && whereItem.getOperator() == OperatorType.EQUALS_TO) { + if (column.isPrimaryKey() && OperatorType.EQUALS_TO.equals(whereItem.getOperator())) { logger.debug("Query is a primary key lookup query. Trying executePrimaryKeyLookupQuery(...)"); if (table != null) { if (isMainSchemaTable(table)) { @@ -430,7 +430,7 @@ public abstract class QueryPostprocessDataContext extends AbstractDataContext im schemaNames[1] = getMainSchemaName(); return schemaNames; } - + @Override protected String getDefaultSchemaName() throws MetaModelException { return getMainSchemaName(); @@ -618,7 +618,7 @@ public abstract class QueryPostprocessDataContext extends AbstractDataContext im protected DataSet materializeMainSchemaTable(Table table, List<SelectItem> selectItems, List<FilterItem> whereItems, int firstRow, int maxRows) { final List<SelectItem> workingSelectItems = buildWorkingSelectItems(selectItems, whereItems); - DataSet dataSet; + DataSet dataSet; if (whereItems.isEmpty()) { // paging is pushed down to materializeMainSchemaTable dataSet = materializeMainSchemaTable(table, workingSelectItems, firstRow, maxRows); http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/core/src/main/java/org/apache/metamodel/query/FilterItem.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/query/FilterItem.java b/core/src/main/java/org/apache/metamodel/query/FilterItem.java index 9984401..6fb7578 100644 --- a/core/src/main/java/org/apache/metamodel/query/FilterItem.java +++ b/core/src/main/java/org/apache/metamodel/query/FilterItem.java @@ -291,34 +291,12 @@ public class FilterItem extends BaseObject implements QueryItem, Cloneable, IRow } public static Object appendOperator(StringBuilder sb, Object operand, OperatorType operator) { - switch (operator) { - case DIFFERENT_FROM: - sb.append(" <> "); - break; - case EQUALS_TO: - sb.append(" = "); - break; - case LIKE: - sb.append(" LIKE "); - break; - case GREATER_THAN: - sb.append(" > "); - break; - case GREATER_THAN_OR_EQUAL: - sb.append(" >= "); - break; - case LESS_THAN: - sb.append(" < "); - break; - case LESS_THAN_OR_EQUAL: - sb.append(" <= "); - break; - case IN: - sb.append(" IN "); + sb.append(' '); + sb.append(operator.toSql()); + sb.append(' '); + + if (operator == OperatorType.IN) { operand = CollectionUtils.toList(operand); - break; - default: - throw new IllegalStateException("Operator could not be determined"); } return operand; } http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/core/src/main/java/org/apache/metamodel/query/OperatorType.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/query/OperatorType.java b/core/src/main/java/org/apache/metamodel/query/OperatorType.java index e668da8..d20f492 100644 --- a/core/src/main/java/org/apache/metamodel/query/OperatorType.java +++ b/core/src/main/java/org/apache/metamodel/query/OperatorType.java @@ -23,58 +23,35 @@ package org.apache.metamodel.query; * * @see FilterItem */ -public enum OperatorType { +public interface OperatorType { - EQUALS_TO("=", false), + public static final OperatorType EQUALS_TO = new OperatorTypeImpl("=", false); - DIFFERENT_FROM("<>", false), + public static final OperatorType DIFFERENT_FROM = new OperatorTypeImpl("<>", false); - LIKE("LIKE", true), + public static final OperatorType LIKE = new OperatorTypeImpl("LIKE", true); - GREATER_THAN(">", false), + public static final OperatorType GREATER_THAN = new OperatorTypeImpl(">", false); - GREATER_THAN_OR_EQUAL(">=", false), + public static final OperatorType GREATER_THAN_OR_EQUAL = new OperatorTypeImpl(">=", false); - LESS_THAN("<", false), + public static final OperatorType LESS_THAN = new OperatorTypeImpl("<", false); - LESS_THAN_OR_EQUAL("<=", false), + public static final OperatorType LESS_THAN_OR_EQUAL = new OperatorTypeImpl("<=", false); - IN("IN", true); + public static final OperatorType IN = new OperatorTypeImpl("IN", true); - private final String _sql; - private final boolean _spaceDelimited; - - private OperatorType(String sql, boolean spaceDelimited) { - _sql = sql; - _spaceDelimited = spaceDelimited; - } + public static final OperatorType[] BUILT_IN_OPERATORS = new OperatorType[] { EQUALS_TO, DIFFERENT_FROM, LIKE, + GREATER_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, IN }; /** * Determines if this operator requires a space delimitor. Operators that are written using letters usually require * space delimitation whereas sign-based operators such as "=" and "<" can be applied even without any delimitaton. + * + * @return */ - public boolean isSpaceDelimited() { - return _spaceDelimited; - } + public boolean isSpaceDelimited(); - public String toSql() { - return _sql; - } + public String toSql(); -/** - * Converts from SQL string literals to an OperatorType. Valid SQL values are "=", "<>", "LIKE", ">", ">=", "<" and - * "<=". - * - * @return a OperatorType object representing the specified SQL type - */ - public static OperatorType convertOperatorType(String sqlType) { - if (sqlType != null) { - for (OperatorType operator : values()) { - if (sqlType.equals(operator.toSql())) { - return operator; - } - } - } - return null; - } } http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/core/src/main/java/org/apache/metamodel/query/OperatorTypeImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/query/OperatorTypeImpl.java b/core/src/main/java/org/apache/metamodel/query/OperatorTypeImpl.java new file mode 100644 index 0000000..9869c88 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/query/OperatorTypeImpl.java @@ -0,0 +1,114 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.metamodel.query; + +import java.util.Objects; + +/** + * Simple implementation of {@link OperatorType} + */ +public class OperatorTypeImpl implements OperatorType { + + private final String _sql; + private final boolean _spaceDelimited; + + public OperatorTypeImpl(String sql, boolean spaceDelimited) { + _sql = sql; + _spaceDelimited = spaceDelimited; + } + + @Override + public boolean isSpaceDelimited() { + return _spaceDelimited; + } + + @Override + public String toSql() { + return _sql; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + if (obj instanceof OperatorType) { + // we only require another OperatorType, not necesarily an _Impl_. + // This is to allow other implementations that wrap this. For + // instance the implementation provided by + // LegacyDeserializationObjectInputStream. + final OperatorType other = (OperatorType) obj; + return isSpaceDelimited() == other.isSpaceDelimited() && Objects.equals(toSql(), other.toSql()); + } + return false; + } + +/** + * Converts from SQL string literals to an OperatorType. Valid SQL values are "=", "<>", "LIKE", ">", ">=", "<" and + * "<=". + * + * @param sqlType + * @return a OperatorType object representing the specified SQL type + */ + public static OperatorType convertOperatorType(String sqlType) { + if (sqlType != null) { + sqlType = sqlType.trim().toUpperCase(); + switch (sqlType) { + case "=": + case "==": + case "EQ": + case "EQUALS_TO": + return OperatorType.EQUALS_TO; + case "<>": + case "!=": + case "NE": + case "NOT_EQUAL": + case "NOT_EQUAL_TO": + case "NOT_EQUALS": + case "NOT_EQUALS_TO": + case "DIFFERENT_FROM": + return OperatorType.DIFFERENT_FROM; + case ">": + case "GT": + case "GREATER_THAN": + return OperatorType.GREATER_THAN; + case ">=": + case "=>": + case "GREATER_THAN_OR_EQUAL": + return OperatorType.GREATER_THAN_OR_EQUAL; + case "IN": + return OperatorType.IN; + case "<": + case "LT": + case "LESS_THAN": + return OperatorType.LESS_THAN; + case "<=": + case "=<": + case "LESS_THAN_OR_EQUAL": + return OperatorType.LESS_THAN_OR_EQUAL; + case "LIKE": + return OperatorType.LIKE; + } + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/core/src/main/java/org/apache/metamodel/query/Query.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/query/Query.java b/core/src/main/java/org/apache/metamodel/query/Query.java index a1df7ea..ae1e530 100644 --- a/core/src/main/java/org/apache/metamodel/query/Query.java +++ b/core/src/main/java/org/apache/metamodel/query/Query.java @@ -320,7 +320,7 @@ public final class Query extends BaseObject implements Cloneable, Serializable { final String rightSide; { String rightSideCandidate = null; - final OperatorType[] operators = OperatorType.values(); + final OperatorType[] operators = OperatorType.BUILT_IN_OPERATORS; for (OperatorType operatorCandidate : operators) { final String searchStr; if (operatorCandidate.isSpaceDelimited()) { http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/core/src/main/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStream.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStream.java b/core/src/main/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStream.java index c1125ea..289f823 100644 --- a/core/src/main/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStream.java +++ b/core/src/main/java/org/apache/metamodel/util/LegacyDeserializationObjectInputStream.java @@ -18,39 +18,70 @@ */ package org.apache.metamodel.util; -import static org.apache.metamodel.schema.SuperColumnType.BINARY_TYPE; -import static org.apache.metamodel.schema.SuperColumnType.BOOLEAN_TYPE; -import static org.apache.metamodel.schema.SuperColumnType.LITERAL_TYPE; -import static org.apache.metamodel.schema.SuperColumnType.NUMBER_TYPE; -import static org.apache.metamodel.schema.SuperColumnType.OTHER_TYPE; -import static org.apache.metamodel.schema.SuperColumnType.TIME_TYPE; - import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; -import java.lang.reflect.Field; -import java.math.BigInteger; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Types; +import java.lang.reflect.Method; import java.util.Comparator; -import java.util.Date; -import java.util.List; -import java.util.Map; +import org.apache.metamodel.query.AggregateFunction; +import org.apache.metamodel.query.FunctionType; +import org.apache.metamodel.query.OperatorType; import org.apache.metamodel.schema.ColumnType; -import org.apache.metamodel.schema.JdbcTypes; import org.apache.metamodel.schema.SuperColumnType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A specialized {@link ObjectInputStream} for MetaModel which can be used or * extended if it is needed to deserialize legacy MetaModel objects. This is - * needed since the namespace of MetaModel was changed from - * org.apache.metamodel to org.apache.metamodel. + * needed since the namespace of MetaModel was changed from org.apache.metamodel + * to org.apache.metamodel. */ public class LegacyDeserializationObjectInputStream extends ObjectInputStream { + private static final Logger logger = LoggerFactory.getLogger(LegacyDeserializationObjectInputStream.class); + + /** + * Implementation of the new {@link FunctionType} and + * {@link AggregateFunction} interfaces which still adheres to the + * constant/enum values of the old FunctionType definition. While + * deserializing old FunctionType objects, we will convert them to this + * enum. + */ + protected static enum LegacyFunctionType implements AggregateFunction { + + COUNT(FunctionType.COUNT), AVG(FunctionType.AVG), SUM(FunctionType.SUM), MAX(FunctionType.MAX), MIN( + FunctionType.MIN); + + private final AggregateFunction _delegate; + + private LegacyFunctionType(AggregateFunction delegate) { + _delegate = delegate; + } + + @Override + public ColumnType getExpectedColumnType(ColumnType type) { + return _delegate.getExpectedColumnType(type); + } + + @Override + public String getFunctionName() { + return _delegate.getFunctionName(); + } + + @Override + public AggregateBuilder<?> createAggregateBuilder() { + return _delegate.createAggregateBuilder(); + } + + @Override + public Object evaluate(Object... values) { + return _delegate.evaluate(values); + } + } + /** * Implementation of the new {@link ColumnType} interface which still * adheres to the constant/enum values of the old ColumnType definition. @@ -59,174 +90,113 @@ public class LegacyDeserializationObjectInputStream extends ObjectInputStream { */ protected static enum LegacyColumnType implements ColumnType { - /** - * Literal - */ - CHAR(LITERAL_TYPE), VARCHAR(LITERAL_TYPE), LONGVARCHAR(LITERAL_TYPE), CLOB(LITERAL_TYPE), NCHAR(LITERAL_TYPE), NVARCHAR( - LITERAL_TYPE), LONGNVARCHAR(LITERAL_TYPE), NCLOB(LITERAL_TYPE), - - /** - * Numbers - */ - TINYINT(NUMBER_TYPE), SMALLINT(NUMBER_TYPE), INTEGER(NUMBER_TYPE), BIGINT(NUMBER_TYPE), FLOAT(NUMBER_TYPE), REAL( - NUMBER_TYPE), DOUBLE(NUMBER_TYPE), NUMERIC(NUMBER_TYPE), DECIMAL(NUMBER_TYPE), - - /** - * Time based - */ - DATE(TIME_TYPE), TIME(TIME_TYPE), TIMESTAMP(TIME_TYPE), - - /** - * Booleans - */ - BIT(BOOLEAN_TYPE), BOOLEAN(BOOLEAN_TYPE), - - /** - * Binary types - */ - BINARY(BINARY_TYPE), VARBINARY(BINARY_TYPE), LONGVARBINARY(BINARY_TYPE), BLOB(BINARY_TYPE), - - /** - * Other types (as defined in {@link Types}). - */ - NULL(OTHER_TYPE), OTHER(OTHER_TYPE), JAVA_OBJECT(OTHER_TYPE), DISTINCT(OTHER_TYPE), STRUCT(OTHER_TYPE), ARRAY( - OTHER_TYPE), REF(OTHER_TYPE), DATALINK(OTHER_TYPE), ROWID(OTHER_TYPE), SQLXML(OTHER_TYPE), - - /** - * Additional types (added by MetaModel for non-JDBC datastores) - */ - LIST(OTHER_TYPE), MAP(OTHER_TYPE); - - private final SuperColumnType _superType; - - private LegacyColumnType(SuperColumnType superType) { - if (superType == null) { - throw new IllegalArgumentException("SuperColumnType cannot be null"); - } - _superType = superType; + CHAR(ColumnType.CHAR), VARCHAR(ColumnType.VARCHAR), LONGVARCHAR(ColumnType.LONGVARCHAR), CLOB(ColumnType.CLOB), NCHAR( + ColumnType.NCHAR), NVARCHAR(ColumnType.NVARCHAR), LONGNVARCHAR(ColumnType.LONGNVARCHAR), NCLOB( + ColumnType.NCLOB), TINYINT(ColumnType.TINYINT), SMALLINT(ColumnType.SMALLINT), INTEGER( + ColumnType.INTEGER), BIGINT(ColumnType.BIGINT), FLOAT(ColumnType.FLOAT), REAL(ColumnType.REAL), DOUBLE( + ColumnType.DOUBLE), NUMERIC(ColumnType.NUMERIC), DECIMAL(ColumnType.DECIMAL), DATE(ColumnType.DATE), TIME( + ColumnType.TIME), TIMESTAMP(ColumnType.TIMESTAMP), BIT(ColumnType.BIT), BOOLEAN(ColumnType.BOOLEAN), BINARY( + ColumnType.BINARY), VARBINARY(ColumnType.VARBINARY), LONGVARBINARY(ColumnType.LONGVARBINARY), BLOB( + ColumnType.BLOB), NULL(ColumnType.NULL), OTHER(ColumnType.OTHER), JAVA_OBJECT(ColumnType.JAVA_OBJECT), DISTINCT( + ColumnType.DISTINCT), STRUCT(ColumnType.STRUCT), ARRAY(ColumnType.ARRAY), REF(ColumnType.REF), DATALINK( + ColumnType.DATALINK), ROWID(ColumnType.ROWID), SQLXML(ColumnType.SQLXML), LIST(ColumnType.LIST), MAP( + ColumnType.MAP); + + private final ColumnType _delegate; + + private LegacyColumnType(ColumnType delegate) { + _delegate = delegate; } @Override public String getName() { - return name(); + return _delegate.getName(); } @Override public Comparator<Object> getComparator() { - if (isTimeBased()) { - return TimeComparator.getComparator(); - } - if (isNumber()) { - return NumberComparator.getComparator(); - } - if (isLiteral()) { - return ToStringComparator.getComparator(); - } - return ObjectComparator.getComparator(); + return _delegate.getComparator(); } @Override public boolean isBoolean() { - return _superType == BOOLEAN_TYPE; + return _delegate.isBoolean(); } @Override public boolean isBinary() { - return _superType == BINARY_TYPE; + return _delegate.isBinary(); } @Override public boolean isNumber() { - return _superType == NUMBER_TYPE; + return _delegate.isNumber(); } @Override public boolean isTimeBased() { - return _superType == TIME_TYPE; + return _delegate.isTimeBased(); } @Override public boolean isLiteral() { - return _superType == LITERAL_TYPE; + return _delegate.isLiteral(); } @Override public boolean isLargeObject() { - switch (this) { - case BLOB: - case CLOB: - case NCLOB: - return true; - default: - return false; - } + return _delegate.isLargeObject(); } @Override public Class<?> getJavaEquivalentClass() { - switch (this) { - case TINYINT: - case SMALLINT: - return Short.class; - case INTEGER: - return Integer.class; - case BIGINT: - return BigInteger.class; - case DECIMAL: - case NUMERIC: - case FLOAT: - case REAL: - case DOUBLE: - return Double.class; - case DATE: - case TIME: - case TIMESTAMP: - return Date.class; - case BLOB: - return Blob.class; - case CLOB: - case NCLOB: - return Clob.class; - case MAP: - return Map.class; - case LIST: - return List.class; - default: - // All other types have fitting java equivalent classes in the - // super - // type - return _superType.getJavaEquivalentClass(); - } + return _delegate.getJavaEquivalentClass(); } @Override public SuperColumnType getSuperType() { - return _superType; + return _delegate.getSuperType(); } @Override public int getJdbcType() throws IllegalStateException { - final String name = this.toString(); - try { - // We assume that the JdbcTypes class only consists of constant - // integer types, so we make no assertions here - final Field[] fields = JdbcTypes.class.getFields(); - for (int i = 0; i < fields.length; i++) { - Field field = fields[i]; - String fieldName = field.getName(); - if (fieldName.equals(name)) { - int value = (Integer) field.getInt(null); - return value; - } - } - throw new IllegalStateException("No JdbcType found with field name: " + name); - } catch (Exception e) { - throw new IllegalStateException("Could not access fields in JdbcTypes", e); - } + return _delegate.getJdbcType(); + } + } + + /** + * Implementation of the new {@link OperatorType} interface which still + * adheres to the constant/enum values of the old OperatorType definition. + * While deserializing old OperatorType objects, we will convert them to + * this enum. + */ + protected static enum LegacyOperatorType implements OperatorType { + + EQUALS_TO(OperatorType.EQUALS_TO), DIFFERENT_FROM(OperatorType.DIFFERENT_FROM), LIKE(OperatorType.LIKE), GREATER_THAN( + OperatorType.GREATER_THAN), GREATER_THAN_OR_EQUAL(OperatorType.GREATER_THAN_OR_EQUAL), LESS_THAN( + OperatorType.LESS_THAN), LESS_THAN_OR_EQUAL(OperatorType.LESS_THAN_OR_EQUAL), IN(OperatorType.IN); + + private final OperatorType _delegate; + + private LegacyOperatorType(OperatorType delegate) { + _delegate = delegate; } + + @Override + public boolean isSpaceDelimited() { + return _delegate.isSpaceDelimited(); + } + + @Override + public String toSql() { + return _delegate.toSql(); + } + } private static final String OLD_CLASS_NAME_COLUMN_TYPE = "org.eobjects.metamodel.schema.ColumnType"; + private static final String CLASS_NAME_OPERATOR_TYPE = "org.apache.metamodel.query.OperatorType"; + private static final String CLASS_NAME_FUNCTION_TYPE = "org.apache.metamodel.query.FunctionType"; public LegacyDeserializationObjectInputStream(InputStream in) throws IOException, SecurityException { super(in); @@ -252,10 +222,44 @@ public class LegacyDeserializationObjectInputStream extends ObjectInputStream { @Override protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { final ObjectStreamClass objectStreamClass = super.readClassDescriptor(); - if (OLD_CLASS_NAME_COLUMN_TYPE.equals(objectStreamClass.getName())) { - final ObjectStreamClass result = ObjectStreamClass.lookup(LegacyColumnType.class); - return result; + final String className = objectStreamClass.getName(); + switch (className) { + case OLD_CLASS_NAME_COLUMN_TYPE: + final ObjectStreamClass legacyColumnTypeResult = ObjectStreamClass.lookup(LegacyColumnType.class); + return legacyColumnTypeResult; + case CLASS_NAME_OPERATOR_TYPE: + if (isEnumExpected(objectStreamClass)) { + final ObjectStreamClass legacyOperatorTypeResult = ObjectStreamClass.lookup(LegacyOperatorType.class); + return legacyOperatorTypeResult; + } + break; + case CLASS_NAME_FUNCTION_TYPE: + if (isEnumExpected(objectStreamClass)) { + final ObjectStreamClass legacyOperatorTypeResult = ObjectStreamClass.lookup(LegacyOperatorType.class); + return legacyOperatorTypeResult; + } + break; } return objectStreamClass; } + + /** + * Method that uses the (non-public) isEnum() method of + * {@link ObjectStreamClass} to determine if an enum is expected. + * + * @param objectStreamClass + * @return + */ + private boolean isEnumExpected(ObjectStreamClass objectStreamClass) { + try { + final Method isEnumMethod = ObjectStreamClass.class.getDeclaredMethod("isEnum"); + isEnumMethod.setAccessible(true); + final Boolean result = (Boolean) isEnumMethod.invoke(objectStreamClass); + return result.booleanValue(); + } catch (Exception e) { + logger.warn("Failed to access and invoke ObjectStreamClass.isEnum to determine if {} is an enum", + objectStreamClass.getName(), e); + } + return false; + } } http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/core/src/test/java/org/apache/metamodel/query/OperatorTypeTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/metamodel/query/OperatorTypeTest.java b/core/src/test/java/org/apache/metamodel/query/OperatorTypeTest.java index 1a3f1f1..c460734 100644 --- a/core/src/test/java/org/apache/metamodel/query/OperatorTypeTest.java +++ b/core/src/test/java/org/apache/metamodel/query/OperatorTypeTest.java @@ -22,13 +22,42 @@ import junit.framework.TestCase; public class OperatorTypeTest extends TestCase { - public void testConvertOperatorType() throws Exception { - assertEquals(OperatorType.EQUALS_TO, OperatorType.convertOperatorType("=")); - assertEquals(OperatorType.GREATER_THAN, OperatorType.convertOperatorType(">")); - assertEquals(OperatorType.LESS_THAN, OperatorType.convertOperatorType("<")); - assertEquals(OperatorType.DIFFERENT_FROM, OperatorType.convertOperatorType("<>")); - assertEquals(OperatorType.LIKE, OperatorType.convertOperatorType("LIKE")); - assertEquals(OperatorType.IN, OperatorType.convertOperatorType("IN")); - assertEquals(null, OperatorType.convertOperatorType("foo")); + public void testConvertOperatorTypeNormal() throws Exception { + assertEquals(OperatorType.EQUALS_TO, OperatorTypeImpl.convertOperatorType("=")); + assertEquals(OperatorType.GREATER_THAN, OperatorTypeImpl.convertOperatorType(">")); + assertEquals(OperatorType.LESS_THAN, OperatorTypeImpl.convertOperatorType("<")); + assertEquals(OperatorType.DIFFERENT_FROM, OperatorTypeImpl.convertOperatorType("<>")); + assertEquals(OperatorType.LIKE, OperatorTypeImpl.convertOperatorType("LIKE")); + assertEquals(OperatorType.IN, OperatorTypeImpl.convertOperatorType("IN")); + assertEquals(null, OperatorTypeImpl.convertOperatorType("foo")); + } + + public void testConvertOperatorTypeAliases() throws Exception { + assertEquals(OperatorType.EQUALS_TO, OperatorTypeImpl.convertOperatorType("eq")); + assertEquals(OperatorType.EQUALS_TO, OperatorTypeImpl.convertOperatorType("EQ")); + assertEquals(OperatorType.EQUALS_TO, OperatorTypeImpl.convertOperatorType("EQUALS_TO")); + assertEquals(OperatorType.EQUALS_TO, OperatorTypeImpl.convertOperatorType("==")); + assertEquals(OperatorType.DIFFERENT_FROM, OperatorTypeImpl.convertOperatorType("!=")); + assertEquals(OperatorType.DIFFERENT_FROM, OperatorTypeImpl.convertOperatorType("DIFFERENT_FROM")); + assertEquals(OperatorType.DIFFERENT_FROM, OperatorTypeImpl.convertOperatorType("ne")); + assertEquals(OperatorType.DIFFERENT_FROM, OperatorTypeImpl.convertOperatorType("NOT_EQUALS_TO")); + assertEquals(OperatorType.DIFFERENT_FROM, OperatorTypeImpl.convertOperatorType("NOT_EQUAL_TO")); + assertEquals(OperatorType.IN, OperatorTypeImpl.convertOperatorType("in")); + assertEquals(OperatorType.IN, OperatorTypeImpl.convertOperatorType("IN")); + assertEquals(OperatorType.GREATER_THAN, OperatorTypeImpl.convertOperatorType("GREATER_THAN")); + assertEquals(OperatorType.GREATER_THAN, OperatorTypeImpl.convertOperatorType("GT")); + assertEquals(OperatorType.GREATER_THAN_OR_EQUAL, OperatorTypeImpl.convertOperatorType(">=")); + assertEquals(OperatorType.GREATER_THAN_OR_EQUAL, OperatorTypeImpl.convertOperatorType("=>")); + assertEquals(OperatorType.GREATER_THAN_OR_EQUAL, OperatorTypeImpl.convertOperatorType("GREATER_THAN_OR_EQUAL")); + assertEquals(OperatorType.LESS_THAN, OperatorTypeImpl.convertOperatorType("lt")); + assertEquals(OperatorType.LESS_THAN, OperatorTypeImpl.convertOperatorType("LESS_THAN")); + assertEquals(OperatorType.LESS_THAN_OR_EQUAL, OperatorTypeImpl.convertOperatorType("<=")); + assertEquals(OperatorType.LESS_THAN_OR_EQUAL, OperatorTypeImpl.convertOperatorType("=<")); + assertEquals(OperatorType.LESS_THAN_OR_EQUAL, OperatorTypeImpl.convertOperatorType("LESS_THAN_OR_EQUAL")); + assertEquals(OperatorType.LIKE, OperatorTypeImpl.convertOperatorType("like")); + } + + public void testConvertOperatorTypeTrimmed() throws Exception { + assertEquals(OperatorType.EQUALS_TO, OperatorTypeImpl.convertOperatorType(" = ")); } } http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/core/src/test/java/org/apache/metamodel/util/FormatHelperTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/metamodel/util/FormatHelperTest.java b/core/src/test/java/org/apache/metamodel/util/FormatHelperTest.java index f2ef4d6..fc6164a 100644 --- a/core/src/test/java/org/apache/metamodel/util/FormatHelperTest.java +++ b/core/src/test/java/org/apache/metamodel/util/FormatHelperTest.java @@ -34,7 +34,6 @@ public class FormatHelperTest extends TestCase { assertEquals("20.1", format.format(20.1)); } - @SuppressWarnings("unchecked") public void testFormatSqlValue() throws Exception { assertEquals("'foo'", FormatHelper.formatSqlValue(null, "foo")); assertEquals("1", FormatHelper.formatSqlValue(null, 1)); http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/elasticsearch/src/main/java/org/apache/metamodel/elasticsearch/ElasticSearchDataContext.java ---------------------------------------------------------------------- diff --git a/elasticsearch/src/main/java/org/apache/metamodel/elasticsearch/ElasticSearchDataContext.java b/elasticsearch/src/main/java/org/apache/metamodel/elasticsearch/ElasticSearchDataContext.java index 7bdd1ab..6d8d5b4 100644 --- a/elasticsearch/src/main/java/org/apache/metamodel/elasticsearch/ElasticSearchDataContext.java +++ b/elasticsearch/src/main/java/org/apache/metamodel/elasticsearch/ElasticSearchDataContext.java @@ -340,33 +340,23 @@ public class ElasticSearchDataContext extends QueryPostprocessDataContext implem final Object operand = item.getOperand(); final OperatorType operator = item.getOperator(); - switch (operator) { - case EQUALS_TO: + if (OperatorType.EQUALS_TO.equals(operator)) { if (operand == null) { - itemQueryBuilder = - QueryBuilders.filteredQuery(null, FilterBuilders.missingFilter(fieldName)); + itemQueryBuilder = QueryBuilders.filteredQuery(null, FilterBuilders.missingFilter(fieldName)); } else { itemQueryBuilder = QueryBuilders.termQuery(fieldName, operand); } - break; - case DIFFERENT_FROM: + } else if (OperatorType.DIFFERENT_FROM.equals(operator)) { if (operand == null) { - itemQueryBuilder = - QueryBuilders.filteredQuery(null, FilterBuilders.existsFilter(fieldName)); + itemQueryBuilder = QueryBuilders.filteredQuery(null, FilterBuilders.existsFilter(fieldName)); } else { - itemQueryBuilder = QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery(fieldName, operand)); + itemQueryBuilder = QueryBuilders.boolQuery().mustNot( + QueryBuilders.termQuery(fieldName, operand)); } - break; - case IN: + } else if (OperatorType.IN.equals(operator)) { final List<?> operands = CollectionUtils.toList(operand); itemQueryBuilder = QueryBuilders.termsQuery(fieldName, operands); - break; - case LIKE: - case GREATER_THAN_OR_EQUAL: - case GREATER_THAN: - case LESS_THAN: - case LESS_THAN_OR_EQUAL: - default: + } else { // not (yet) support operator types return null; } http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/elasticsearch/src/test/java/org/apache/metamodel/elasticsearch/ElasticSearchDataContextTest.java ---------------------------------------------------------------------- diff --git a/elasticsearch/src/test/java/org/apache/metamodel/elasticsearch/ElasticSearchDataContextTest.java b/elasticsearch/src/test/java/org/apache/metamodel/elasticsearch/ElasticSearchDataContextTest.java index 6390dea..efd0c97 100644 --- a/elasticsearch/src/test/java/org/apache/metamodel/elasticsearch/ElasticSearchDataContextTest.java +++ b/elasticsearch/src/test/java/org/apache/metamodel/elasticsearch/ElasticSearchDataContextTest.java @@ -571,4 +571,4 @@ public class ElasticSearchDataContextTest { return jsonBuilder().startObject().field("gender", gender).field("age", age).field("id", elementId).endObject(); } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUtils.java ---------------------------------------------------------------------- diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUtils.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUtils.java index a6065ae..ea06751 100644 --- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUtils.java +++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUtils.java @@ -229,7 +229,7 @@ public final class JdbcUtils { * @return */ public static boolean isPreparedParameterCandidate(FilterItem whereItem) { - return !whereItem.isCompoundFilter() && whereItem.getOperator() != OperatorType.IN + return !whereItem.isCompoundFilter() && !OperatorType.IN.equals(whereItem.getOperator()) && whereItem.getOperand() != null; } http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/AbstractQueryRewriter.java ---------------------------------------------------------------------- diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/AbstractQueryRewriter.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/AbstractQueryRewriter.java index 16ec985..05453df 100644 --- a/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/AbstractQueryRewriter.java +++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/AbstractQueryRewriter.java @@ -215,7 +215,7 @@ public abstract class AbstractQueryRewriter implements IQueryRewriter { final String primaryFilterSql = item.toSql(isSchemaIncludedInColumnPaths()); final OperatorType operator = item.getOperator(); - if (operator == OperatorType.DIFFERENT_FROM) { + if (OperatorType.DIFFERENT_FROM.equals(operator)) { final Object operand = item.getOperand(); if (operand != null) { // special case in SQL where NULL is not treated as a value - http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DB2QueryRewriter.java ---------------------------------------------------------------------- diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DB2QueryRewriter.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DB2QueryRewriter.java index 0a4c31e..fa8ebe0 100644 --- a/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DB2QueryRewriter.java +++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DB2QueryRewriter.java @@ -111,7 +111,8 @@ public class DB2QueryRewriter extends DefaultQueryRewriter implements IQueryRewr return baseQueryString + " WHERE metamodel_row_number > " + (firstRow - 1); } - return baseQueryString + " WHERE metamodel_row_number BETWEEN " + firstRow + " AND " + (firstRow - 1 + maxRows); + return baseQueryString + " WHERE metamodel_row_number BETWEEN " + firstRow + " AND " + + (firstRow - 1 + maxRows); } } @@ -125,26 +126,26 @@ public class DB2QueryRewriter extends DefaultQueryRewriter implements IQueryRewr @Override public String rewriteFilterItem(FilterItem item) { - SelectItem _selectItem = item.getSelectItem(); - Object _operand = item.getOperand(); - OperatorType _operator = item.getOperator(); - if (null != _selectItem && _operand != null) { - ColumnType columnType = _selectItem.getExpectedColumnType(); + final SelectItem selectItem = item.getSelectItem(); + final Object itemOperand = item.getOperand(); + final OperatorType operator = item.getOperator(); + if (null != selectItem && itemOperand != null) { + ColumnType columnType = selectItem.getExpectedColumnType(); if (columnType != null) { if (columnType.isTimeBased()) { // special logic for DB2 based time operands. StringBuilder sb = new StringBuilder(); - sb.append(_selectItem.getSameQueryAlias(true)); - final Object operand = FilterItem.appendOperator(sb, _operand, _operator); + sb.append(selectItem.getSameQueryAlias(true)); + final Object operand = FilterItem.appendOperator(sb, itemOperand, operator); if (operand instanceof SelectItem) { final String selectItemString = ((SelectItem) operand).getSameQueryAlias(true); sb.append(selectItemString); } else { - Date date = TimeComparator.toDate(_operand); + Date date = TimeComparator.toDate(itemOperand); if (date == null) { - throw new IllegalStateException("Could not convert " + _operand + " to date"); + throw new IllegalStateException("Could not convert " + itemOperand + " to date"); } final String sqlValue = FormatHelper.formatSqlTime(columnType, date, true, "('", "')"); http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DefaultQueryRewriter.java ---------------------------------------------------------------------- diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DefaultQueryRewriter.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DefaultQueryRewriter.java index e44df06..288bf78 100644 --- a/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DefaultQueryRewriter.java +++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/dialects/DefaultQueryRewriter.java @@ -117,7 +117,7 @@ public class DefaultQueryRewriter extends AbstractQueryRewriter { // operand is a set of values (typically in combination with an // IN operator). Each individual element must be escaped. - assert item.getOperator() == OperatorType.IN; + assert OperatorType.IN.equals(item.getOperator()); @SuppressWarnings("unchecked") final List<Object> elements = (List<Object>) CollectionUtils.toList(operand); http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/mongodb/src/main/java/org/apache/metamodel/mongodb/MongoDbDataContext.java ---------------------------------------------------------------------- diff --git a/mongodb/src/main/java/org/apache/metamodel/mongodb/MongoDbDataContext.java b/mongodb/src/main/java/org/apache/metamodel/mongodb/MongoDbDataContext.java index 5e89b6d..73adea4 100644 --- a/mongodb/src/main/java/org/apache/metamodel/mongodb/MongoDbDataContext.java +++ b/mongodb/src/main/java/org/apache/metamodel/mongodb/MongoDbDataContext.java @@ -306,7 +306,7 @@ public class MongoDbDataContext extends QueryPostprocessDataContext implements U final SelectItem selectItem = whereItem.getSelectItem(); if (!whereItem.isCompoundFilter() && selectItem != null && selectItem.getColumn() != null) { final Column column = selectItem.getColumn(); - if (column.isPrimaryKey() && whereItem.getOperator() == OperatorType.EQUALS_TO) { + if (column.isPrimaryKey() && OperatorType.EQUALS_TO.equals(whereItem.getOperator())) { logger.debug("Query is a primary key lookup query. Trying executePrimaryKeyLookupQuery(...)"); final Object operand = whereItem.getOperand(); final Row row = executePrimaryKeyLookupQuery(table, selectItems, column, operand); @@ -392,10 +392,9 @@ public class MongoDbDataContext extends QueryPostprocessDataContext implements U final BasicDBObject existingFilterObject = (BasicDBObject) query.get(columnName); if (existingFilterObject == null) { if (operatorName == null) { - if (item.getOperator().equals(OperatorType.LIKE)) { + if (OperatorType.LIKE.equals(item.getOperator())) { query.put(columnName, turnOperandIntoRegExp(operand)); - } - else { + } else { query.put(columnName, operand); } } else { @@ -412,34 +411,34 @@ public class MongoDbDataContext extends QueryPostprocessDataContext implements U } private String getOperatorName(FilterItem item) { - final String operatorName; - switch (item.getOperator()) { - case EQUALS_TO: - case LIKE: - operatorName = null; - break; - case LESS_THAN: - operatorName = "$lt"; - break; - case LESS_THAN_OR_EQUAL: - operatorName = "$lte"; - break; - case GREATER_THAN: - operatorName = "$gt"; - break; - case GREATER_THAN_OR_EQUAL: - operatorName = "$gte"; - break; - case DIFFERENT_FROM: - operatorName = "$ne"; - break; - case IN: - operatorName = "$in"; - break; - default: - throw new IllegalStateException("Unsupported operator type: " + item.getOperator()); + final OperatorType operator = item.getOperator(); + + if (OperatorType.EQUALS_TO.equals(operator)) { + return null; + } + if (OperatorType.LIKE.equals(operator)) { + return null; + } + if (OperatorType.LESS_THAN.equals(operator)) { + return "$lt"; + } + if (OperatorType.LESS_THAN_OR_EQUAL.equals(operator)) { + return "$lte"; } - return operatorName; + if (OperatorType.GREATER_THAN.equals(operator)) { + return "$gt"; + } + if (OperatorType.GREATER_THAN_OR_EQUAL.equals(operator)) { + return "$gte"; + } + if (OperatorType.DIFFERENT_FROM.equals(operator)) { + return "$ne"; + } + if (OperatorType.IN.equals(operator)) { + return "$in"; + } + + throw new IllegalStateException("Unsupported operator type: " + operator); } private Pattern turnOperandIntoRegExp(Object operand) { http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceDataContext.java ---------------------------------------------------------------------- diff --git a/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceDataContext.java b/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceDataContext.java index 730aaae..c8add52 100644 --- a/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceDataContext.java +++ b/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceDataContext.java @@ -269,7 +269,7 @@ public class SalesforceDataContext extends QueryPostprocessDataContext implement sb.append(' '); final OperatorType operator = filterItem.getOperator(); - if (operator == OperatorType.IN) { + if (OperatorType.IN.equals(operator)) { throw new UnsupportedOperationException("IN operator not supported: " + filterItem); } sb.append(operator.toSql()); http://git-wip-us.apache.org/repos/asf/metamodel/blob/b417bc9c/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceUpdateCallback.java ---------------------------------------------------------------------- diff --git a/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceUpdateCallback.java b/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceUpdateCallback.java index 21669d3..757cb95 100644 --- a/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceUpdateCallback.java +++ b/salesforce/src/main/java/org/apache/metamodel/salesforce/SalesforceUpdateCallback.java @@ -233,7 +233,7 @@ final class SalesforceUpdateCallback extends AbstractUpdateCallback implements C final OperatorType operator = whereItem.getOperator(); - if (operator != OperatorType.EQUALS_TO && operator != OperatorType.IN) { + if (!OperatorType.EQUALS_TO.equals(operator) && !OperatorType.IN.equals(operator)) { throw new IllegalStateException( "Salesforce only allows deletion of records by their specific IDs. Violated by operator in where item: " + whereItem);
