| /* |
| * 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.drill.exec.record; |
| |
| import org.apache.drill.common.expression.SchemaPath; |
| import org.apache.drill.exec.ops.FragmentContext; |
| import org.apache.drill.exec.vector.ValueVector; |
| |
| /** |
| * A record batch contains a set of field values for a particular range of |
| * records. |
| * <p> |
| * In the case of a record batch composed of ValueVectors, ideally a batch |
| * fits within L2 cache (~256kB per core). The set of value vectors does |
| * not change except during a call to {@link #next()} that returns |
| * {@link IterOutcome#OK_NEW_SCHEMA} value. |
| * </p> |
| * <p> |
| * A key thing to know is that the Iterator provided by a record batch must |
| * align with the rank positions of the field IDs provided using |
| * {@link #getValueVectorId}. |
| * </p> |
| */ |
| public interface RecordBatch extends VectorAccessible { |
| |
| /** max num of rows in a batch, limited by 2-byte length in SV2: 65536 = 2^16 */ |
| int MAX_BATCH_ROW_COUNT = ValueVector.MAX_ROW_COUNT; |
| |
| /** |
| * Describes the outcome of incrementing RecordBatch forward by a call to |
| * {@link #next()}. |
| * <p> |
| * Key characteristics of the return value sequence: |
| * </p> |
| * <ul> |
| * <li> |
| * {@code OK_NEW_SCHEMA} always appears unless {@code STOP} appears. (A |
| * batch returns {@code OK_NEW_SCHEMA} before returning {@code NONE} even |
| * if the batch has zero rows.) |
| * </li> |
| * <li>{@code OK_NEW_SCHEMA} always appears before {@code OK} appears.</li> |
| * <li> |
| * The last value is always {@code NONE} or {@code STOP}, and {@code NONE} |
| * and {@code STOP} appear only as the last value. |
| * </li> |
| * </ul> |
| * <p> |
| * <strong>Details</strong>: |
| * </p> |
| * <p> |
| * For normal completion, the basic sequence of return values from calls to |
| * {@code next()} on a {@code RecordBatch} is: |
| * </p> |
| * <ol> |
| * <li> |
| * an {@link #OK_NEW_SCHEMA} value followed by zero or more {@link #OK} |
| * values, |
| * </li> |
| * <li> |
| * zero or more subsequences each having an {@code OK_NEW_SCHEMA} value |
| * followed by zero or more {@code OK} values, and then |
| * </li> |
| * <li> |
| * a {@link #NONE} value. |
| * </li> |
| * </ol> |
| * <p> |
| * In addition to that basic sequence, {@link #NOT_YET} and |
| * {@link #OUT_OF_MEMORY} values can appear anywhere in the subsequence |
| * before the terminal value ({@code NONE} or {@code STOP}). |
| * </p> |
| * <p> |
| * For abnormal termination, the sequence is truncated (before the |
| * {@code NONE}) and ends with {@link #STOP}. That is, the sequence begins |
| * with a subsequence that is some prefix of a normal-completion sequence |
| * and that does not contain {@code NONE}, and ends with {@code STOP}. |
| * </p> |
| * <p> |
| * (The normal-completion return sequence is matched by the following |
| * regular-expression-style grammar: |
| * <pre> |
| * ( ( NOT_YET | OUT_OF_MEMORY )* OK_NEW_SCHEMA |
| * ( NOT_YET | OUT_OF_MEMORY )* OK )* |
| * )+ |
| * ( NOT_YET | OUT_OF_+MEMORY )* NONE |
| * </pre> |
| * ) |
| * </p> |
| */ |
| enum IterOutcome { |
| /** |
| * Normal completion of batch. |
| * <p> |
| * The call to {@link #next()} |
| * read no records, |
| * the batch has and will have no more results to return, |
| * and {@code next()} must not be called again. |
| * </p> |
| * <p> |
| * This value will be returned only after {@link #OK_NEW_SCHEMA} has been |
| * returned at least once (not necessarily <em>immediately</em> after). |
| * </p> |
| * <p> |
| * Also after a RecordBatch returns NONE a RecordBatch should: |
| * <ul> |
| * <li>Contain the last valid schema seen by the operator.</li> |
| * <li>Contain a VectorContainer with empty columns corresponding to the last valid schema.</li> |
| * <li>Return a record count of 0.</li> |
| * </ul> |
| * </p> |
| */ |
| NONE(false), |
| |
| /** |
| * Zero or more records with same schema. |
| * <p> |
| * The call to {@link #next()} |
| * read zero or more records, |
| * the schema has not changed since the last time {@code OK_NEW_SCHEMA} |
| * was returned, |
| * and the batch will have more results to return (at least completion or |
| * abnormal termination ({@code NONE} or {@code STOP})). |
| * ({@code next()} should be called again.) |
| * </p> |
| * <p> |
| * This will be returned only after {@link #OK_NEW_SCHEMA} has been |
| * returned at least once (not necessarily <em>immediately</em> after). |
| * </p> |
| */ |
| OK(false), |
| |
| /** |
| * New schema, maybe with records. |
| * <p> |
| * The call to {@link #next()} |
| * changed the schema and vector structures |
| * and read zero or more records, |
| * and the batch will have more results to return (at least completion or |
| * abnormal termination ({@code NONE} or {@code STOP})). |
| * ({@code next()} should be called again.) |
| * </p> |
| */ |
| OK_NEW_SCHEMA(false), |
| |
| /** |
| * Non-completion (abnormal) termination. |
| * <p> |
| * The call to {@link #next()} |
| * reports that the query has terminated other than by normal completion, |
| * and that the caller must not call any of the schema-access or |
| * data-access methods nor call {@code next()} again. |
| * </p> |
| * <p> |
| * The caller can consume its QueryContext to understand the current state |
| * of things. |
| * </p> |
| */ |
| STOP(true), |
| |
| /** |
| * No data yet. |
| * <p> |
| * The call to {@link #next()} |
| * read no data, |
| * and the batch will have more results to return in the future (at least |
| * completion or abnormal termination ({@code NONE} or {@code STOP})). |
| * The caller should call {@code next()} again, but should do so later |
| * (including by returning {@code NOT_YET} to its caller). |
| * </p> |
| * <p> |
| * Normally, the caller should perform any locally available work while |
| * waiting for incoming data from the callee, for example, doing partial |
| * sorts on already received data while waiting for additional data to |
| * sort. |
| * </p> |
| * <p> |
| * Used by batches that haven't received incoming data yet. |
| * </p> |
| */ |
| NOT_YET(false), |
| |
| /** |
| * Out of memory (not fatal). |
| * <p> |
| * The call to {@link #next()}, |
| * including upstream operators, was unable to allocate memory |
| * and did not read any records, |
| * and the batch will have more results to return (at least completion or |
| * abnormal termination ({@code NONE} or {@code STOP})). |
| * The caller should release memory if it can (including by returning |
| * {@code OUT_OF_MEMORY} to its caller) and call {@code next()} again. |
| * </p> |
| */ |
| OUT_OF_MEMORY(true), |
| |
| /** |
| * Emit record to produce output batches. |
| * <p> |
| * The call to {@link #next()}, |
| * read zero or more records with no change in schema as compared to last |
| * time. It is an indication from upstream operator to unblock and |
| * produce an output batch based on all the records current operator |
| * possess. The caller should return this outcome to it's downstream |
| * operators except LateralJoinRecordBatch, which will consume any EMIT |
| * from right branch but will pass through EMIT from left branch. |
| * </p> |
| * <p> |
| * Caller should produce one or more output record batch based on all the |
| * current data and restart fresh for any new input. If there are multiple |
| * output batches then caller should send EMIT only with last batch and OK |
| * with all previous batches. |
| * For example: Hash Join when received EMIT on build side will stop build |
| * side and call next() on probe side until it sees EMIT. On seeing EMIT |
| * from probe side, it should perform JOIN and produce output batches. |
| * Later it should clear all the data on both build and probe side of |
| * input and again start from build side. |
| * </p> |
| */ |
| EMIT(false); |
| |
| private boolean error; |
| |
| IterOutcome(boolean error) { |
| this.error = error; |
| } |
| |
| public boolean isError() { |
| return error; |
| } |
| } |
| |
| /** |
| * Gets the FragmentContext of the current query fragment. Useful for |
| * reporting failure information or other query-level information. |
| */ |
| FragmentContext getContext(); |
| |
| /** |
| * Gets the current schema of this record batch. |
| * <p> |
| * May be called only when the most recent call to {@link #next}, if any, |
| * returned {@link IterOutcome#OK_NEW_SCHEMA} or {@link IterOutcome#OK}. |
| * </p> |
| * <p> |
| * The schema changes when and only when {@link #next} returns |
| * {@link IterOutcome#OK_NEW_SCHEMA}. |
| * </p> |
| */ |
| @Override |
| BatchSchema getSchema(); |
| |
| /** |
| * Informs child nodes that this query should be terminated. Child nodes |
| * should use the QueryContext to determine what has happened. |
| */ |
| void kill(boolean sendUpstream); |
| |
| VectorContainer getOutgoingContainer(); |
| |
| /** |
| * Return the internal vector container |
| * |
| * @return The internal vector container |
| */ |
| VectorContainer getContainer(); |
| |
| /** |
| * Gets the value vector type and ID for the given schema path. The |
| * TypedFieldId should store a fieldId which is the same as the ordinal |
| * position of the field within the Iterator provided this class's |
| * implementation of Iterable<ValueVector>. |
| * |
| * @param path |
| * The path where the vector should be located. |
| * @return The local field id associated with this vector. If no field matches this path, this will return a null |
| * TypedFieldId |
| */ |
| @Override |
| TypedFieldId getValueVectorId(SchemaPath path); |
| |
| @Override |
| VectorWrapper<?> getValueAccessorById(Class<?> clazz, int... ids); |
| |
| /** |
| * Updates the data in each Field reading interface for the next range of |
| * records. |
| * <p> |
| * Once a RecordBatch's {@code next()} has returned {@link IterOutcome#NONE} |
| * or {@link IterOutcome#STOP}, the consumer should no longer call |
| * {@code next()}. Behavior at this point is undefined and likely to |
| * throw an exception. |
| * </p> |
| * <p> |
| * See {@link IterOutcome} for the protocol (possible sequences of return |
| * values). |
| * </p> |
| * |
| * |
| * @return An IterOutcome describing the result of the iteration. |
| */ |
| IterOutcome next(); |
| |
| /** |
| * Gets a writable version of this batch. Takes over ownership of existing |
| * buffers. |
| */ |
| WritableBatch getWritableBatch(); |
| |
| /** |
| * Perform dump of this batch's state to logs. |
| */ |
| void dump(); |
| |
| /** |
| * Use this method to see if the batch has failed. Currently used when logging {@code RecordBatch}'s |
| * state using {@link #dump()} method. |
| * |
| * @return {@code true} if either {@link org.apache.drill.exec.record.RecordBatch.IterOutcome#STOP} |
| * was returned by its or child's {@link #next()} invocation or there was an {@code Exception} thrown |
| * during execution of the batch; {@code false} otherwise |
| */ |
| boolean hasFailed(); |
| } |