/* * Licensed to Crate under one or more contributor license agreements. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. Crate 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. * * However, if you have executed another commercial license agreement * with Crate these terms will supersede the license and you may use the * software solely pursuant to the terms of the relevant commercial * agreement. */ package io.crate.planner; import io.crate.analyze.OrderBy; import io.crate.analyze.symbol.Symbol; import io.crate.planner.consumer.OrderByPositionVisitor; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import javax.annotation.Nullable; import java.io.IOException; import java.util.Arrays; import java.util.List; public class PositionalOrderBy { private final int[] indices; private final boolean[] reverseFlags; private final Boolean[] nullsFirst; private PositionalOrderBy(int[] indices, boolean[] reverseFlags, Boolean[] nullsFirst) { assert indices.length == reverseFlags.length && reverseFlags.length == nullsFirst.length : "all parameters to OrderByPositions must have the same length"; // PositionalOrderBy should be null if there is no order by assert indices.length > 0 : "parameters must have length > 0"; this.indices = indices; this.reverseFlags = reverseFlags; this.nullsFirst = nullsFirst; } public int[] indices() { return indices; } public boolean[] reverseFlags() { return reverseFlags; } public Boolean[] nullsFirst() { return nullsFirst; } @Override public String toString() { return "OrderByPositions{" + "indices=" + Arrays.toString(indices) + ", reverseFlags=" + Arrays.toString(reverseFlags) + ", nullsFirst=" + Arrays.toString(nullsFirst) + '}'; } @Nullable public static PositionalOrderBy fromStream(StreamInput in) throws IOException { int size = in.readVInt(); if (size == 0) { return null; } int[] indices = new int[size]; boolean[] reverseFlags = new boolean[size]; Boolean[] nullsFirst = new Boolean[size]; for (int i = 0; i < size; i++) { indices[i] = in.readVInt(); reverseFlags[i] = in.readBoolean(); nullsFirst[i] = in.readOptionalBoolean(); } return new PositionalOrderBy(indices, reverseFlags, nullsFirst); } public static void toStream(@Nullable PositionalOrderBy orderBy, StreamOutput out) throws IOException { if (orderBy == null) { out.writeVInt(0); return; } out.writeVInt(orderBy.indices.length); for (int i = 0; i < orderBy.indices.length; i++) { out.writeVInt(orderBy.indices[i]); out.writeBoolean(orderBy.reverseFlags[i]); out.writeOptionalBoolean(orderBy.nullsFirst[i]); } } /** * Create OrderByPositions from a OrderBy definition. * * @param orderByInputSymbols symbols which describe the output which should be sorted. * {@link OrderBy#orderBySymbols()} must point to those symbols. * This is used to create the correct indices mapping. */ @Nullable public static PositionalOrderBy of(@Nullable OrderBy orderBy, List<? extends Symbol> orderByInputSymbols) { if (orderBy == null) { return null; } int[] indices = OrderByPositionVisitor.orderByPositions(orderBy.orderBySymbols(), orderByInputSymbols); return new PositionalOrderBy(indices, orderBy.reverseFlags(), orderBy.nullsFirst()); } }