private FilterItem copyFilterItem(FilterItem item, Object[] values, AtomicInteger parameterIndex) { if (item.isCompoundFilter()) { final FilterItem[] childItems = item.getChildItems(); final FilterItem[] newChildItems = new FilterItem[childItems.length]; for (int i = 0; i < childItems.length; i++) { final FilterItem childItem = childItems[i]; final FilterItem newChildItem = copyFilterItem(childItem, values, parameterIndex); newChildItems[i] = newChildItem; } final FilterItem newFilter = new FilterItem(item.getLogicalOperator(), newChildItems); return newFilter; } else { if (item.getOperand() instanceof QueryParameter) { final Object newOperand = values[parameterIndex.getAndIncrement()]; final FilterItem newFilter = new FilterItem(item.getSelectItem(), item.getOperator(), newOperand); return newFilter; } else { return item; } } }
@Override public boolean accept(Row row) { return evaluate(row); } }
@Override public String toString() { return toSql(); }
/** * Determines if a particular {@link FilterItem} will have it's parameter (operand) replaced during SQL generation. * Such filter items should succesively have their parameters set at execution time. * * @param whereItem * @return */ public static boolean isPreparedParameterCandidate(FilterItem whereItem) { return !whereItem.isCompoundFilter() && !OperatorType.IN.equals(whereItem.getOperator()) && whereItem.getOperand() != null; }
private void buildParameterFromFilterItem(List<QueryParameter> parameters, FilterItem item) { if (item.isCompoundFilter()) { FilterItem[] childItems = item.getChildItems(); for (FilterItem childItem : childItems) { buildParameterFromFilterItem(parameters, childItem); } } else { if (item.getOperand() instanceof QueryParameter) { parameters.add((QueryParameter) item.getOperand()); } } }
@Override public String rewriteFilterItem(final FilterItem item) { if (item.getOperand() instanceof String && item.getOperand().equals("")) { // In Oracle empty strings are treated as null. Typical SQL constructs with an empty string do not work. return super.rewriteFilterItem(new FilterItem(item.getSelectItem(), item.getOperator(), null)); } else { return super.rewriteFilterItem(item); } } }
/** * Filters the FilterItems such that only the FilterItems are returned, which contain SelectItems that are contained * in selectItemList * * @param filters * @param selectItemList * @return */ private static Set<FilterItem> applicableFilters(Collection<FilterItem> filters, Collection<SelectItem> selectItemList) { Set<SelectItem> items = new HashSet<SelectItem>(selectItemList); return filters.stream().filter(fi -> { Collection<SelectItem> fiSelectItems = new ArrayList<>(); fiSelectItems.add(fi.getSelectItem()); Object operand = fi.getOperand(); if (operand instanceof SelectItem) { fiSelectItems.add((SelectItem) operand); } return items.containsAll(fiSelectItems); }).collect(Collectors.toSet()); }
private boolean isOptimizable(FilterItem whereItem) { if (whereItem.isCompoundFilter()) { return false; } if (whereItem.getExpression() != null) { return false; } final SelectItem selectItem = whereItem.getSelectItem(); if (selectItem.getExpression() != null || selectItem.getAggregateFunction() != null || selectItem .getScalarFunction() != null) { return false; } final Column column = selectItem.getColumn(); if (column == null) { return false; } switch (column.getName()) { case COLUMN_OFFSET: return OPTIMIZED_OFFSET_OPERATORS.contains(whereItem.getOperator()); case COLUMN_PARTITION: return OPTIMIZED_PARTITION_OPERATORS.contains(whereItem.getOperator()); default: return false; } }
private static String buildWhereClauseItem(final FilterItem whereItem, final String queryObjectHandle) { final StringBuilder whereClauseItemBuilder = new StringBuilder(); whereClauseItemBuilder.append(queryObjectHandle); whereClauseItemBuilder.append("."); whereClauseItemBuilder.append(whereItem.getSelectItem().getColumn().getName()); whereClauseItemBuilder.append(whereItem.getOperator().toSql()); final Object operand = whereItem.getOperand(); if (operand instanceof String) { whereClauseItemBuilder.append("\""); } whereClauseItemBuilder.append(operand); if (operand instanceof String) { whereClauseItemBuilder.append("\""); } return whereClauseItemBuilder.toString(); } }
private Query lowerQuery(final Query query, final SelectItem selectItem) { // special case, null is also considered "lower" final FilterItem isNullFilter = new FilterItem(selectItem, OperatorType.EQUALS_TO, null); final FilterItem isLowerThanFilter = new FilterItem(selectItem, OperatorType.LESS_THAN, getLowestValue()); query.where(new FilterItem(isNullFilter, isLowerThanFilter)); return query; } }
private static void addEvaluatedSelectItems(List<SelectItem> result, FilterItem item) { final FilterItem[] orItems = item.getChildItems(); if (orItems != null) { for (FilterItem filterItem : orItems) { addEvaluatedSelectItems(result, filterItem); } } final SelectItem selectItem = item.getSelectItem(); if (selectItem != null && !result.contains(selectItem)) { result.add(selectItem); } final Object operand = item.getOperand(); if (operand != null && operand instanceof SelectItem && !result.contains(operand)) { result.add((SelectItem) operand); } }
public static String createWhereClause(List<FilterItem> whereItems, IQueryRewriter queryRewriter, boolean inlineValues) { if (whereItems.isEmpty()) { return ""; } StringBuilder sb = new StringBuilder(); sb.append(" WHERE "); boolean firstValue = true; for (FilterItem whereItem : whereItems) { if (firstValue) { firstValue = false; } else { sb.append(" AND "); } if (!inlineValues) { if (isPreparedParameterCandidate(whereItem)) { // replace operator with parameter whereItem = new FilterItem(whereItem.getSelectItem(), whereItem.getOperator(), new QueryParameter()); } } final String whereItemLabel = queryRewriter.rewriteFilterItem(whereItem); sb.append(whereItemLabel); } return sb.toString(); }
@Override public String rewriteFilterItem(FilterItem item) { if (!item.isCompoundFilter()) { final SelectItem selectItem = item.getSelectItem(); final Column column = selectItem.getColumn(); if (column != null) { if (column.getType() == ColumnType.TIMESTAMP) { // HSQLDB does not treat (TIMESTAMP 'yyyy-MM-dd hh:mm:ss') // tokens correctly String result = super.rewriteFilterItem(item); int indexOfTimestamp = result.lastIndexOf("TIMESTAMP"); if (indexOfTimestamp != -1) { result = result.substring(0, indexOfTimestamp) + result.substring(indexOfTimestamp + "TIMESTAMP".length()); } return result; } } } return super.rewriteFilterItem(item); }
public static DataSet getFiltered(DataSet dataSet, Collection<FilterItem> filterItems) { if (filterItems == null || filterItems.isEmpty()) { return dataSet; } final List<SelectItem> selectItemsOnOutput = dataSet.getSelectItems(); final Iterable<SelectItem> selectItems = filterItems.stream().map(f -> f.getSelectItem()).filter(s -> s != null)::iterator; final List<SelectItem> scalarFunctionSelectItems = getUnmaterializedScalarFunctionSelectItems(selectItems, dataSet); final boolean calculateScalarFunctions = !scalarFunctionSelectItems.isEmpty(); if (calculateScalarFunctions) { // scalar functions are needed in evaluation of the filters dataSet = new ScalarFunctionDataSet(scalarFunctionSelectItems, dataSet); } final FilteredDataSet filteredDataSet = new FilteredDataSet(dataSet, filterItems); if (calculateScalarFunctions) { return getSelection(selectItemsOnOutput, filteredDataSet); } else { return filteredDataSet; } }
private String getOperatorName(FilterItem item) { 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"; } 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); }
public CompareFilter.Category filter(final Object value, final Operator operator, final Object operand) { // use MetaModel FilterItem to do the evaluation - it's a bit of a // detour, but there's a ton of operator/operand combinations to take // care of which is already done there. final FilterItem item = new FilterItem(compareSelectItem, operator.getOperatorType(), operand); final boolean evaluation = item.evaluate( new DefaultRow(new SimpleDataSetHeader(Collections.singletonList(compareSelectItem)), new Object[] { value })); if (evaluation) { return Category.TRUE; } else { return Category.FALSE; } }
sb.append(" IS NOT NULL"); } else { final Object operand = appendOperator(sb, _operand, _operator); sb.append(' '); sb.append(item.toSql());
@Override public String rewriteFilterItem(final FilterItem item) { if (item.getOperand() instanceof String && item.getOperand().equals("")) { // In Oracle empty strings are treated as null. Typical SQL constructs with an empty string do not work. return super.rewriteFilterItem(new FilterItem(item.getSelectItem(), item.getOperator(), null)); } else { return super.rewriteFilterItem(item); } } }
/** * Filters the FilterItems such that only the FilterItems are returned, which contain SelectItems that are contained * in selectItemList * * @param filters * @param selectItemList * @return */ private static Set<FilterItem> applicableFilters(Collection<FilterItem> filters, Collection<SelectItem> selectItemList) { Set<SelectItem> items = new HashSet<SelectItem>(selectItemList); return filters.stream().filter(fi -> { Collection<SelectItem> fiSelectItems = new ArrayList<>(); fiSelectItems.add(fi.getSelectItem()); Object operand = fi.getOperand(); if (operand instanceof SelectItem) { fiSelectItems.add((SelectItem) operand); } return items.containsAll(fiSelectItems); }).collect(Collectors.toSet()); }