/*
 * 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.
 */
// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: ExecutionProtos.proto

package org.apache.drill.exec.proto;

public final class ExecProtos {
  private ExecProtos() {}
  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistryLite registry) {
  }

  public static void registerAllExtensions(
      com.google.protobuf.ExtensionRegistry registry) {
    registerAllExtensions(
        (com.google.protobuf.ExtensionRegistryLite) registry);
  }
  public interface FragmentHandleOrBuilder extends
      // @@protoc_insertion_point(interface_extends:exec.bit.FragmentHandle)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     * @return Whether the queryId field is set.
     */
    boolean hasQueryId();
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     * @return The queryId.
     */
    org.apache.drill.exec.proto.UserBitShared.QueryId getQueryId();
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     */
    org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder getQueryIdOrBuilder();

    /**
     * <code>optional int32 major_fragment_id = 2;</code>
     * @return Whether the majorFragmentId field is set.
     */
    boolean hasMajorFragmentId();
    /**
     * <code>optional int32 major_fragment_id = 2;</code>
     * @return The majorFragmentId.
     */
    int getMajorFragmentId();

    /**
     * <code>optional int32 minor_fragment_id = 3;</code>
     * @return Whether the minorFragmentId field is set.
     */
    boolean hasMinorFragmentId();
    /**
     * <code>optional int32 minor_fragment_id = 3;</code>
     * @return The minorFragmentId.
     */
    int getMinorFragmentId();

    /**
     * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
     * @return Whether the parentQueryId field is set.
     */
    boolean hasParentQueryId();
    /**
     * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
     * @return The parentQueryId.
     */
    org.apache.drill.exec.proto.UserBitShared.QueryId getParentQueryId();
    /**
     * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
     */
    org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder getParentQueryIdOrBuilder();
  }
  /**
   * Protobuf type {@code exec.bit.FragmentHandle}
   */
  public static final class FragmentHandle extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:exec.bit.FragmentHandle)
      FragmentHandleOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use FragmentHandle.newBuilder() to construct.
    private FragmentHandle(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private FragmentHandle() {
    }

    @java.lang.Override
    @SuppressWarnings({"unused"})
    protected java.lang.Object newInstance(
        UnusedPrivateParameter unused) {
      return new FragmentHandle();
    }

    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
    getUnknownFields() {
      return this.unknownFields;
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.drill.exec.proto.ExecProtos.internal_static_exec_bit_FragmentHandle_descriptor;
    }

    @java.lang.Override
    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.drill.exec.proto.ExecProtos.internal_static_exec_bit_FragmentHandle_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.drill.exec.proto.ExecProtos.FragmentHandle.class, org.apache.drill.exec.proto.ExecProtos.FragmentHandle.Builder.class);
    }

    private int bitField0_;
    public static final int QUERY_ID_FIELD_NUMBER = 1;
    private org.apache.drill.exec.proto.UserBitShared.QueryId queryId_;
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     * @return Whether the queryId field is set.
     */
    @java.lang.Override
    public boolean hasQueryId() {
      return ((bitField0_ & 0x00000001) != 0);
    }
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     * @return The queryId.
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.UserBitShared.QueryId getQueryId() {
      return queryId_ == null ? org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : queryId_;
    }
    /**
     * <code>optional .exec.shared.QueryId query_id = 1;</code>
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder getQueryIdOrBuilder() {
      return queryId_ == null ? org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : queryId_;
    }

    public static final int MAJOR_FRAGMENT_ID_FIELD_NUMBER = 2;
    private int majorFragmentId_;
    /**
     * <code>optional int32 major_fragment_id = 2;</code>
     * @return Whether the majorFragmentId field is set.
     */
    @java.lang.Override
    public boolean hasMajorFragmentId() {
      return ((bitField0_ & 0x00000002) != 0);
    }
    /**
     * <code>optional int32 major_fragment_id = 2;</code>
     * @return The majorFragmentId.
     */
    @java.lang.Override
    public int getMajorFragmentId() {
      return majorFragmentId_;
    }

    public static final int MINOR_FRAGMENT_ID_FIELD_NUMBER = 3;
    private int minorFragmentId_;
    /**
     * <code>optional int32 minor_fragment_id = 3;</code>
     * @return Whether the minorFragmentId field is set.
     */
    @java.lang.Override
    public boolean hasMinorFragmentId() {
      return ((bitField0_ & 0x00000004) != 0);
    }
    /**
     * <code>optional int32 minor_fragment_id = 3;</code>
     * @return The minorFragmentId.
     */
    @java.lang.Override
    public int getMinorFragmentId() {
      return minorFragmentId_;
    }

    public static final int PARENT_QUERY_ID_FIELD_NUMBER = 4;
    private org.apache.drill.exec.proto.UserBitShared.QueryId parentQueryId_;
    /**
     * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
     * @return Whether the parentQueryId field is set.
     */
    @java.lang.Override
    public boolean hasParentQueryId() {
      return ((bitField0_ & 0x00000008) != 0);
    }
    /**
     * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
     * @return The parentQueryId.
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.UserBitShared.QueryId getParentQueryId() {
      return parentQueryId_ == null ? org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : parentQueryId_;
    }
    /**
     * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
     */
    @java.lang.Override
    public org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder getParentQueryIdOrBuilder() {
      return parentQueryId_ == null ? org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : parentQueryId_;
    }

    private byte memoizedIsInitialized = -1;
    @java.lang.Override
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized == 1) return true;
      if (isInitialized == 0) return false;

      memoizedIsInitialized = 1;
      return true;
    }

    @java.lang.Override
    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      if (((bitField0_ & 0x00000001) != 0)) {
        output.writeMessage(1, getQueryId());
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        output.writeInt32(2, majorFragmentId_);
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        output.writeInt32(3, minorFragmentId_);
      }
      if (((bitField0_ & 0x00000008) != 0)) {
        output.writeMessage(4, getParentQueryId());
      }
      getUnknownFields().writeTo(output);
    }

    @java.lang.Override
    public int getSerializedSize() {
      int size = memoizedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeMessageSize(1, getQueryId());
      }
      if (((bitField0_ & 0x00000002) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(2, majorFragmentId_);
      }
      if (((bitField0_ & 0x00000004) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeInt32Size(3, minorFragmentId_);
      }
      if (((bitField0_ & 0x00000008) != 0)) {
        size += com.google.protobuf.CodedOutputStream
          .computeMessageSize(4, getParentQueryId());
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSize = size;
      return size;
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.drill.exec.proto.ExecProtos.FragmentHandle)) {
        return super.equals(obj);
      }
      org.apache.drill.exec.proto.ExecProtos.FragmentHandle other = (org.apache.drill.exec.proto.ExecProtos.FragmentHandle) obj;

      if (hasQueryId() != other.hasQueryId()) return false;
      if (hasQueryId()) {
        if (!getQueryId()
            .equals(other.getQueryId())) return false;
      }
      if (hasMajorFragmentId() != other.hasMajorFragmentId()) return false;
      if (hasMajorFragmentId()) {
        if (getMajorFragmentId()
            != other.getMajorFragmentId()) return false;
      }
      if (hasMinorFragmentId() != other.hasMinorFragmentId()) return false;
      if (hasMinorFragmentId()) {
        if (getMinorFragmentId()
            != other.getMinorFragmentId()) return false;
      }
      if (hasParentQueryId() != other.hasParentQueryId()) return false;
      if (hasParentQueryId()) {
        if (!getParentQueryId()
            .equals(other.getParentQueryId())) return false;
      }
      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
      return true;
    }

    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptor().hashCode();
      if (hasQueryId()) {
        hash = (37 * hash) + QUERY_ID_FIELD_NUMBER;
        hash = (53 * hash) + getQueryId().hashCode();
      }
      if (hasMajorFragmentId()) {
        hash = (37 * hash) + MAJOR_FRAGMENT_ID_FIELD_NUMBER;
        hash = (53 * hash) + getMajorFragmentId();
      }
      if (hasMinorFragmentId()) {
        hash = (37 * hash) + MINOR_FRAGMENT_ID_FIELD_NUMBER;
        hash = (53 * hash) + getMinorFragmentId();
      }
      if (hasParentQueryId()) {
        hash = (37 * hash) + PARENT_QUERY_ID_FIELD_NUMBER;
        hash = (53 * hash) + getParentQueryId().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.drill.exec.proto.ExecProtos.FragmentHandle parseFrom(
        java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.ExecProtos.FragmentHandle parseFrom(
        java.nio.ByteBuffer data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.ExecProtos.FragmentHandle parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.ExecProtos.FragmentHandle parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.ExecProtos.FragmentHandle parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.ExecProtos.FragmentHandle parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.ExecProtos.FragmentHandle parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.ExecProtos.FragmentHandle parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.ExecProtos.FragmentHandle parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.ExecProtos.FragmentHandle parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.ExecProtos.FragmentHandle parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.ExecProtos.FragmentHandle parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }

    @java.lang.Override
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder() {
      return DEFAULT_INSTANCE.toBuilder();
    }
    public static Builder newBuilder(org.apache.drill.exec.proto.ExecProtos.FragmentHandle prototype) {
      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
    }
    @java.lang.Override
    public Builder toBuilder() {
      return this == DEFAULT_INSTANCE
          ? new Builder() : new Builder().mergeFrom(this);
    }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * Protobuf type {@code exec.bit.FragmentHandle}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:exec.bit.FragmentHandle)
        org.apache.drill.exec.proto.ExecProtos.FragmentHandleOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.drill.exec.proto.ExecProtos.internal_static_exec_bit_FragmentHandle_descriptor;
      }

      @java.lang.Override
      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.drill.exec.proto.ExecProtos.internal_static_exec_bit_FragmentHandle_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.drill.exec.proto.ExecProtos.FragmentHandle.class, org.apache.drill.exec.proto.ExecProtos.FragmentHandle.Builder.class);
      }

      // Construct using org.apache.drill.exec.proto.ExecProtos.FragmentHandle.newBuilder()
      private Builder() {
        maybeForceBuilderInitialization();
      }

      private Builder(
          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
        super(parent);
        maybeForceBuilderInitialization();
      }
      private void maybeForceBuilderInitialization() {
        if (com.google.protobuf.GeneratedMessageV3
                .alwaysUseFieldBuilders) {
          getQueryIdFieldBuilder();
          getParentQueryIdFieldBuilder();
        }
      }
      @java.lang.Override
      public Builder clear() {
        super.clear();
        if (queryIdBuilder_ == null) {
          queryId_ = null;
        } else {
          queryIdBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000001);
        majorFragmentId_ = 0;
        bitField0_ = (bitField0_ & ~0x00000002);
        minorFragmentId_ = 0;
        bitField0_ = (bitField0_ & ~0x00000004);
        if (parentQueryIdBuilder_ == null) {
          parentQueryId_ = null;
        } else {
          parentQueryIdBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000008);
        return this;
      }

      @java.lang.Override
      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.drill.exec.proto.ExecProtos.internal_static_exec_bit_FragmentHandle_descriptor;
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.ExecProtos.FragmentHandle getDefaultInstanceForType() {
        return org.apache.drill.exec.proto.ExecProtos.FragmentHandle.getDefaultInstance();
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.ExecProtos.FragmentHandle build() {
        org.apache.drill.exec.proto.ExecProtos.FragmentHandle result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.ExecProtos.FragmentHandle buildPartial() {
        org.apache.drill.exec.proto.ExecProtos.FragmentHandle result = new org.apache.drill.exec.proto.ExecProtos.FragmentHandle(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) != 0)) {
          if (queryIdBuilder_ == null) {
            result.queryId_ = queryId_;
          } else {
            result.queryId_ = queryIdBuilder_.build();
          }
          to_bitField0_ |= 0x00000001;
        }
        if (((from_bitField0_ & 0x00000002) != 0)) {
          result.majorFragmentId_ = majorFragmentId_;
          to_bitField0_ |= 0x00000002;
        }
        if (((from_bitField0_ & 0x00000004) != 0)) {
          result.minorFragmentId_ = minorFragmentId_;
          to_bitField0_ |= 0x00000004;
        }
        if (((from_bitField0_ & 0x00000008) != 0)) {
          if (parentQueryIdBuilder_ == null) {
            result.parentQueryId_ = parentQueryId_;
          } else {
            result.parentQueryId_ = parentQueryIdBuilder_.build();
          }
          to_bitField0_ |= 0x00000008;
        }
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      @java.lang.Override
      public Builder clone() {
        return super.clone();
      }
      @java.lang.Override
      public Builder setField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.setField(field, value);
      }
      @java.lang.Override
      public Builder clearField(
          com.google.protobuf.Descriptors.FieldDescriptor field) {
        return super.clearField(field);
      }
      @java.lang.Override
      public Builder clearOneof(
          com.google.protobuf.Descriptors.OneofDescriptor oneof) {
        return super.clearOneof(oneof);
      }
      @java.lang.Override
      public Builder setRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          int index, java.lang.Object value) {
        return super.setRepeatedField(field, index, value);
      }
      @java.lang.Override
      public Builder addRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.addRepeatedField(field, value);
      }
      @java.lang.Override
      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.drill.exec.proto.ExecProtos.FragmentHandle) {
          return mergeFrom((org.apache.drill.exec.proto.ExecProtos.FragmentHandle)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.drill.exec.proto.ExecProtos.FragmentHandle other) {
        if (other == org.apache.drill.exec.proto.ExecProtos.FragmentHandle.getDefaultInstance()) return this;
        if (other.hasQueryId()) {
          mergeQueryId(other.getQueryId());
        }
        if (other.hasMajorFragmentId()) {
          setMajorFragmentId(other.getMajorFragmentId());
        }
        if (other.hasMinorFragmentId()) {
          setMinorFragmentId(other.getMinorFragmentId());
        }
        if (other.hasParentQueryId()) {
          mergeParentQueryId(other.getParentQueryId());
        }
        this.mergeUnknownFields(other.getUnknownFields());
        onChanged();
        return this;
      }

      @java.lang.Override
      public final boolean isInitialized() {
        return true;
      }

      @java.lang.Override
      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        if (extensionRegistry == null) {
          throw new java.lang.NullPointerException();
        }
        try {
          boolean done = false;
          while (!done) {
            int tag = input.readTag();
            switch (tag) {
              case 0:
                done = true;
                break;
              case 10: {
                input.readMessage(
                    getQueryIdFieldBuilder().getBuilder(),
                    extensionRegistry);
                bitField0_ |= 0x00000001;
                break;
              } // case 10
              case 16: {
                majorFragmentId_ = input.readInt32();
                bitField0_ |= 0x00000002;
                break;
              } // case 16
              case 24: {
                minorFragmentId_ = input.readInt32();
                bitField0_ |= 0x00000004;
                break;
              } // case 24
              case 34: {
                input.readMessage(
                    getParentQueryIdFieldBuilder().getBuilder(),
                    extensionRegistry);
                bitField0_ |= 0x00000008;
                break;
              } // case 34
              default: {
                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
                  done = true; // was an endgroup tag
                }
                break;
              } // default:
            } // switch (tag)
          } // while (!done)
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.unwrapIOException();
        } finally {
          onChanged();
        } // finally
        return this;
      }
      private int bitField0_;

      private org.apache.drill.exec.proto.UserBitShared.QueryId queryId_;
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.UserBitShared.QueryId, org.apache.drill.exec.proto.UserBitShared.QueryId.Builder, org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder> queryIdBuilder_;
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       * @return Whether the queryId field is set.
       */
      public boolean hasQueryId() {
        return ((bitField0_ & 0x00000001) != 0);
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       * @return The queryId.
       */
      public org.apache.drill.exec.proto.UserBitShared.QueryId getQueryId() {
        if (queryIdBuilder_ == null) {
          return queryId_ == null ? org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : queryId_;
        } else {
          return queryIdBuilder_.getMessage();
        }
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public Builder setQueryId(org.apache.drill.exec.proto.UserBitShared.QueryId value) {
        if (queryIdBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          queryId_ = value;
          onChanged();
        } else {
          queryIdBuilder_.setMessage(value);
        }
        bitField0_ |= 0x00000001;
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public Builder setQueryId(
          org.apache.drill.exec.proto.UserBitShared.QueryId.Builder builderForValue) {
        if (queryIdBuilder_ == null) {
          queryId_ = builderForValue.build();
          onChanged();
        } else {
          queryIdBuilder_.setMessage(builderForValue.build());
        }
        bitField0_ |= 0x00000001;
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public Builder mergeQueryId(org.apache.drill.exec.proto.UserBitShared.QueryId value) {
        if (queryIdBuilder_ == null) {
          if (((bitField0_ & 0x00000001) != 0) &&
              queryId_ != null &&
              queryId_ != org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance()) {
            queryId_ =
              org.apache.drill.exec.proto.UserBitShared.QueryId.newBuilder(queryId_).mergeFrom(value).buildPartial();
          } else {
            queryId_ = value;
          }
          onChanged();
        } else {
          queryIdBuilder_.mergeFrom(value);
        }
        bitField0_ |= 0x00000001;
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public Builder clearQueryId() {
        if (queryIdBuilder_ == null) {
          queryId_ = null;
          onChanged();
        } else {
          queryIdBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public org.apache.drill.exec.proto.UserBitShared.QueryId.Builder getQueryIdBuilder() {
        bitField0_ |= 0x00000001;
        onChanged();
        return getQueryIdFieldBuilder().getBuilder();
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      public org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder getQueryIdOrBuilder() {
        if (queryIdBuilder_ != null) {
          return queryIdBuilder_.getMessageOrBuilder();
        } else {
          return queryId_ == null ?
              org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : queryId_;
        }
      }
      /**
       * <code>optional .exec.shared.QueryId query_id = 1;</code>
       */
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.UserBitShared.QueryId, org.apache.drill.exec.proto.UserBitShared.QueryId.Builder, org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder> 
          getQueryIdFieldBuilder() {
        if (queryIdBuilder_ == null) {
          queryIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
              org.apache.drill.exec.proto.UserBitShared.QueryId, org.apache.drill.exec.proto.UserBitShared.QueryId.Builder, org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder>(
                  getQueryId(),
                  getParentForChildren(),
                  isClean());
          queryId_ = null;
        }
        return queryIdBuilder_;
      }

      private int majorFragmentId_ ;
      /**
       * <code>optional int32 major_fragment_id = 2;</code>
       * @return Whether the majorFragmentId field is set.
       */
      @java.lang.Override
      public boolean hasMajorFragmentId() {
        return ((bitField0_ & 0x00000002) != 0);
      }
      /**
       * <code>optional int32 major_fragment_id = 2;</code>
       * @return The majorFragmentId.
       */
      @java.lang.Override
      public int getMajorFragmentId() {
        return majorFragmentId_;
      }
      /**
       * <code>optional int32 major_fragment_id = 2;</code>
       * @param value The majorFragmentId to set.
       * @return This builder for chaining.
       */
      public Builder setMajorFragmentId(int value) {
        bitField0_ |= 0x00000002;
        majorFragmentId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int32 major_fragment_id = 2;</code>
       * @return This builder for chaining.
       */
      public Builder clearMajorFragmentId() {
        bitField0_ = (bitField0_ & ~0x00000002);
        majorFragmentId_ = 0;
        onChanged();
        return this;
      }

      private int minorFragmentId_ ;
      /**
       * <code>optional int32 minor_fragment_id = 3;</code>
       * @return Whether the minorFragmentId field is set.
       */
      @java.lang.Override
      public boolean hasMinorFragmentId() {
        return ((bitField0_ & 0x00000004) != 0);
      }
      /**
       * <code>optional int32 minor_fragment_id = 3;</code>
       * @return The minorFragmentId.
       */
      @java.lang.Override
      public int getMinorFragmentId() {
        return minorFragmentId_;
      }
      /**
       * <code>optional int32 minor_fragment_id = 3;</code>
       * @param value The minorFragmentId to set.
       * @return This builder for chaining.
       */
      public Builder setMinorFragmentId(int value) {
        bitField0_ |= 0x00000004;
        minorFragmentId_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional int32 minor_fragment_id = 3;</code>
       * @return This builder for chaining.
       */
      public Builder clearMinorFragmentId() {
        bitField0_ = (bitField0_ & ~0x00000004);
        minorFragmentId_ = 0;
        onChanged();
        return this;
      }

      private org.apache.drill.exec.proto.UserBitShared.QueryId parentQueryId_;
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.UserBitShared.QueryId, org.apache.drill.exec.proto.UserBitShared.QueryId.Builder, org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder> parentQueryIdBuilder_;
      /**
       * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
       * @return Whether the parentQueryId field is set.
       */
      public boolean hasParentQueryId() {
        return ((bitField0_ & 0x00000008) != 0);
      }
      /**
       * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
       * @return The parentQueryId.
       */
      public org.apache.drill.exec.proto.UserBitShared.QueryId getParentQueryId() {
        if (parentQueryIdBuilder_ == null) {
          return parentQueryId_ == null ? org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : parentQueryId_;
        } else {
          return parentQueryIdBuilder_.getMessage();
        }
      }
      /**
       * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
       */
      public Builder setParentQueryId(org.apache.drill.exec.proto.UserBitShared.QueryId value) {
        if (parentQueryIdBuilder_ == null) {
          if (value == null) {
            throw new NullPointerException();
          }
          parentQueryId_ = value;
          onChanged();
        } else {
          parentQueryIdBuilder_.setMessage(value);
        }
        bitField0_ |= 0x00000008;
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
       */
      public Builder setParentQueryId(
          org.apache.drill.exec.proto.UserBitShared.QueryId.Builder builderForValue) {
        if (parentQueryIdBuilder_ == null) {
          parentQueryId_ = builderForValue.build();
          onChanged();
        } else {
          parentQueryIdBuilder_.setMessage(builderForValue.build());
        }
        bitField0_ |= 0x00000008;
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
       */
      public Builder mergeParentQueryId(org.apache.drill.exec.proto.UserBitShared.QueryId value) {
        if (parentQueryIdBuilder_ == null) {
          if (((bitField0_ & 0x00000008) != 0) &&
              parentQueryId_ != null &&
              parentQueryId_ != org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance()) {
            parentQueryId_ =
              org.apache.drill.exec.proto.UserBitShared.QueryId.newBuilder(parentQueryId_).mergeFrom(value).buildPartial();
          } else {
            parentQueryId_ = value;
          }
          onChanged();
        } else {
          parentQueryIdBuilder_.mergeFrom(value);
        }
        bitField0_ |= 0x00000008;
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
       */
      public Builder clearParentQueryId() {
        if (parentQueryIdBuilder_ == null) {
          parentQueryId_ = null;
          onChanged();
        } else {
          parentQueryIdBuilder_.clear();
        }
        bitField0_ = (bitField0_ & ~0x00000008);
        return this;
      }
      /**
       * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
       */
      public org.apache.drill.exec.proto.UserBitShared.QueryId.Builder getParentQueryIdBuilder() {
        bitField0_ |= 0x00000008;
        onChanged();
        return getParentQueryIdFieldBuilder().getBuilder();
      }
      /**
       * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
       */
      public org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder getParentQueryIdOrBuilder() {
        if (parentQueryIdBuilder_ != null) {
          return parentQueryIdBuilder_.getMessageOrBuilder();
        } else {
          return parentQueryId_ == null ?
              org.apache.drill.exec.proto.UserBitShared.QueryId.getDefaultInstance() : parentQueryId_;
        }
      }
      /**
       * <code>optional .exec.shared.QueryId parent_query_id = 4;</code>
       */
      private com.google.protobuf.SingleFieldBuilderV3<
          org.apache.drill.exec.proto.UserBitShared.QueryId, org.apache.drill.exec.proto.UserBitShared.QueryId.Builder, org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder> 
          getParentQueryIdFieldBuilder() {
        if (parentQueryIdBuilder_ == null) {
          parentQueryIdBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
              org.apache.drill.exec.proto.UserBitShared.QueryId, org.apache.drill.exec.proto.UserBitShared.QueryId.Builder, org.apache.drill.exec.proto.UserBitShared.QueryIdOrBuilder>(
                  getParentQueryId(),
                  getParentForChildren(),
                  isClean());
          parentQueryId_ = null;
        }
        return parentQueryIdBuilder_;
      }
      @java.lang.Override
      public final Builder setUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.setUnknownFields(unknownFields);
      }

      @java.lang.Override
      public final Builder mergeUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.mergeUnknownFields(unknownFields);
      }


      // @@protoc_insertion_point(builder_scope:exec.bit.FragmentHandle)
    }

    // @@protoc_insertion_point(class_scope:exec.bit.FragmentHandle)
    private static final org.apache.drill.exec.proto.ExecProtos.FragmentHandle DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new org.apache.drill.exec.proto.ExecProtos.FragmentHandle();
    }

    public static org.apache.drill.exec.proto.ExecProtos.FragmentHandle getDefaultInstance() {
      return DEFAULT_INSTANCE;
    }

    @java.lang.Deprecated public static final com.google.protobuf.Parser<FragmentHandle>
        PARSER = new com.google.protobuf.AbstractParser<FragmentHandle>() {
      @java.lang.Override
      public FragmentHandle parsePartialFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        Builder builder = newBuilder();
        try {
          builder.mergeFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.setUnfinishedMessage(builder.buildPartial());
        } catch (com.google.protobuf.UninitializedMessageException e) {
          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
        } catch (java.io.IOException e) {
          throw new com.google.protobuf.InvalidProtocolBufferException(e)
              .setUnfinishedMessage(builder.buildPartial());
        }
        return builder.buildPartial();
      }
    };

    public static com.google.protobuf.Parser<FragmentHandle> parser() {
      return PARSER;
    }

    @java.lang.Override
    public com.google.protobuf.Parser<FragmentHandle> getParserForType() {
      return PARSER;
    }

    @java.lang.Override
    public org.apache.drill.exec.proto.ExecProtos.FragmentHandle getDefaultInstanceForType() {
      return DEFAULT_INSTANCE;
    }

  }

  public interface ServerPreparedStatementStateOrBuilder extends
      // @@protoc_insertion_point(interface_extends:exec.bit.ServerPreparedStatementState)
      com.google.protobuf.MessageOrBuilder {

    /**
     * <code>optional string sql_query = 1;</code>
     * @return Whether the sqlQuery field is set.
     */
    boolean hasSqlQuery();
    /**
     * <code>optional string sql_query = 1;</code>
     * @return The sqlQuery.
     */
    java.lang.String getSqlQuery();
    /**
     * <code>optional string sql_query = 1;</code>
     * @return The bytes for sqlQuery.
     */
    com.google.protobuf.ByteString
        getSqlQueryBytes();
  }
  /**
   * <pre>
   * Prepared statement state on server side. Clients do not
   * need to know the contents. They just need to submit it back to
   * server when executing the prepared statement.
   * </pre>
   *
   * Protobuf type {@code exec.bit.ServerPreparedStatementState}
   */
  public static final class ServerPreparedStatementState extends
      com.google.protobuf.GeneratedMessageV3 implements
      // @@protoc_insertion_point(message_implements:exec.bit.ServerPreparedStatementState)
      ServerPreparedStatementStateOrBuilder {
  private static final long serialVersionUID = 0L;
    // Use ServerPreparedStatementState.newBuilder() to construct.
    private ServerPreparedStatementState(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
      super(builder);
    }
    private ServerPreparedStatementState() {
      sqlQuery_ = "";
    }

    @java.lang.Override
    @SuppressWarnings({"unused"})
    protected java.lang.Object newInstance(
        UnusedPrivateParameter unused) {
      return new ServerPreparedStatementState();
    }

    @java.lang.Override
    public final com.google.protobuf.UnknownFieldSet
    getUnknownFields() {
      return this.unknownFields;
    }
    public static final com.google.protobuf.Descriptors.Descriptor
        getDescriptor() {
      return org.apache.drill.exec.proto.ExecProtos.internal_static_exec_bit_ServerPreparedStatementState_descriptor;
    }

    @java.lang.Override
    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
        internalGetFieldAccessorTable() {
      return org.apache.drill.exec.proto.ExecProtos.internal_static_exec_bit_ServerPreparedStatementState_fieldAccessorTable
          .ensureFieldAccessorsInitialized(
              org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState.class, org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState.Builder.class);
    }

    private int bitField0_;
    public static final int SQL_QUERY_FIELD_NUMBER = 1;
    private volatile java.lang.Object sqlQuery_;
    /**
     * <code>optional string sql_query = 1;</code>
     * @return Whether the sqlQuery field is set.
     */
    @java.lang.Override
    public boolean hasSqlQuery() {
      return ((bitField0_ & 0x00000001) != 0);
    }
    /**
     * <code>optional string sql_query = 1;</code>
     * @return The sqlQuery.
     */
    @java.lang.Override
    public java.lang.String getSqlQuery() {
      java.lang.Object ref = sqlQuery_;
      if (ref instanceof java.lang.String) {
        return (java.lang.String) ref;
      } else {
        com.google.protobuf.ByteString bs = 
            (com.google.protobuf.ByteString) ref;
        java.lang.String s = bs.toStringUtf8();
        if (bs.isValidUtf8()) {
          sqlQuery_ = s;
        }
        return s;
      }
    }
    /**
     * <code>optional string sql_query = 1;</code>
     * @return The bytes for sqlQuery.
     */
    @java.lang.Override
    public com.google.protobuf.ByteString
        getSqlQueryBytes() {
      java.lang.Object ref = sqlQuery_;
      if (ref instanceof java.lang.String) {
        com.google.protobuf.ByteString b = 
            com.google.protobuf.ByteString.copyFromUtf8(
                (java.lang.String) ref);
        sqlQuery_ = b;
        return b;
      } else {
        return (com.google.protobuf.ByteString) ref;
      }
    }

    private byte memoizedIsInitialized = -1;
    @java.lang.Override
    public final boolean isInitialized() {
      byte isInitialized = memoizedIsInitialized;
      if (isInitialized == 1) return true;
      if (isInitialized == 0) return false;

      memoizedIsInitialized = 1;
      return true;
    }

    @java.lang.Override
    public void writeTo(com.google.protobuf.CodedOutputStream output)
                        throws java.io.IOException {
      if (((bitField0_ & 0x00000001) != 0)) {
        com.google.protobuf.GeneratedMessageV3.writeString(output, 1, sqlQuery_);
      }
      getUnknownFields().writeTo(output);
    }

    @java.lang.Override
    public int getSerializedSize() {
      int size = memoizedSize;
      if (size != -1) return size;

      size = 0;
      if (((bitField0_ & 0x00000001) != 0)) {
        size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, sqlQuery_);
      }
      size += getUnknownFields().getSerializedSize();
      memoizedSize = size;
      return size;
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object obj) {
      if (obj == this) {
       return true;
      }
      if (!(obj instanceof org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState)) {
        return super.equals(obj);
      }
      org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState other = (org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState) obj;

      if (hasSqlQuery() != other.hasSqlQuery()) return false;
      if (hasSqlQuery()) {
        if (!getSqlQuery()
            .equals(other.getSqlQuery())) return false;
      }
      if (!getUnknownFields().equals(other.getUnknownFields())) return false;
      return true;
    }

    @java.lang.Override
    public int hashCode() {
      if (memoizedHashCode != 0) {
        return memoizedHashCode;
      }
      int hash = 41;
      hash = (19 * hash) + getDescriptor().hashCode();
      if (hasSqlQuery()) {
        hash = (37 * hash) + SQL_QUERY_FIELD_NUMBER;
        hash = (53 * hash) + getSqlQuery().hashCode();
      }
      hash = (29 * hash) + getUnknownFields().hashCode();
      memoizedHashCode = hash;
      return hash;
    }

    public static org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState parseFrom(
        java.nio.ByteBuffer data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState parseFrom(
        java.nio.ByteBuffer data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState parseFrom(
        com.google.protobuf.ByteString data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState parseFrom(
        com.google.protobuf.ByteString data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState parseFrom(byte[] data)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data);
    }
    public static org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState parseFrom(
        byte[] data,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws com.google.protobuf.InvalidProtocolBufferException {
      return PARSER.parseFrom(data, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState parseFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState parseFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState parseDelimitedFrom(java.io.InputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState parseDelimitedFrom(
        java.io.InputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
    }
    public static org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState parseFrom(
        com.google.protobuf.CodedInputStream input)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input);
    }
    public static org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState parseFrom(
        com.google.protobuf.CodedInputStream input,
        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
        throws java.io.IOException {
      return com.google.protobuf.GeneratedMessageV3
          .parseWithIOException(PARSER, input, extensionRegistry);
    }

    @java.lang.Override
    public Builder newBuilderForType() { return newBuilder(); }
    public static Builder newBuilder() {
      return DEFAULT_INSTANCE.toBuilder();
    }
    public static Builder newBuilder(org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState prototype) {
      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
    }
    @java.lang.Override
    public Builder toBuilder() {
      return this == DEFAULT_INSTANCE
          ? new Builder() : new Builder().mergeFrom(this);
    }

    @java.lang.Override
    protected Builder newBuilderForType(
        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
      Builder builder = new Builder(parent);
      return builder;
    }
    /**
     * <pre>
     * Prepared statement state on server side. Clients do not
     * need to know the contents. They just need to submit it back to
     * server when executing the prepared statement.
     * </pre>
     *
     * Protobuf type {@code exec.bit.ServerPreparedStatementState}
     */
    public static final class Builder extends
        com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
        // @@protoc_insertion_point(builder_implements:exec.bit.ServerPreparedStatementState)
        org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementStateOrBuilder {
      public static final com.google.protobuf.Descriptors.Descriptor
          getDescriptor() {
        return org.apache.drill.exec.proto.ExecProtos.internal_static_exec_bit_ServerPreparedStatementState_descriptor;
      }

      @java.lang.Override
      protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
          internalGetFieldAccessorTable() {
        return org.apache.drill.exec.proto.ExecProtos.internal_static_exec_bit_ServerPreparedStatementState_fieldAccessorTable
            .ensureFieldAccessorsInitialized(
                org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState.class, org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState.Builder.class);
      }

      // Construct using org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState.newBuilder()
      private Builder() {

      }

      private Builder(
          com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
        super(parent);

      }
      @java.lang.Override
      public Builder clear() {
        super.clear();
        sqlQuery_ = "";
        bitField0_ = (bitField0_ & ~0x00000001);
        return this;
      }

      @java.lang.Override
      public com.google.protobuf.Descriptors.Descriptor
          getDescriptorForType() {
        return org.apache.drill.exec.proto.ExecProtos.internal_static_exec_bit_ServerPreparedStatementState_descriptor;
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState getDefaultInstanceForType() {
        return org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState.getDefaultInstance();
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState build() {
        org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState result = buildPartial();
        if (!result.isInitialized()) {
          throw newUninitializedMessageException(result);
        }
        return result;
      }

      @java.lang.Override
      public org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState buildPartial() {
        org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState result = new org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState(this);
        int from_bitField0_ = bitField0_;
        int to_bitField0_ = 0;
        if (((from_bitField0_ & 0x00000001) != 0)) {
          to_bitField0_ |= 0x00000001;
        }
        result.sqlQuery_ = sqlQuery_;
        result.bitField0_ = to_bitField0_;
        onBuilt();
        return result;
      }

      @java.lang.Override
      public Builder clone() {
        return super.clone();
      }
      @java.lang.Override
      public Builder setField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.setField(field, value);
      }
      @java.lang.Override
      public Builder clearField(
          com.google.protobuf.Descriptors.FieldDescriptor field) {
        return super.clearField(field);
      }
      @java.lang.Override
      public Builder clearOneof(
          com.google.protobuf.Descriptors.OneofDescriptor oneof) {
        return super.clearOneof(oneof);
      }
      @java.lang.Override
      public Builder setRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          int index, java.lang.Object value) {
        return super.setRepeatedField(field, index, value);
      }
      @java.lang.Override
      public Builder addRepeatedField(
          com.google.protobuf.Descriptors.FieldDescriptor field,
          java.lang.Object value) {
        return super.addRepeatedField(field, value);
      }
      @java.lang.Override
      public Builder mergeFrom(com.google.protobuf.Message other) {
        if (other instanceof org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState) {
          return mergeFrom((org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState)other);
        } else {
          super.mergeFrom(other);
          return this;
        }
      }

      public Builder mergeFrom(org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState other) {
        if (other == org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState.getDefaultInstance()) return this;
        if (other.hasSqlQuery()) {
          bitField0_ |= 0x00000001;
          sqlQuery_ = other.sqlQuery_;
          onChanged();
        }
        this.mergeUnknownFields(other.getUnknownFields());
        onChanged();
        return this;
      }

      @java.lang.Override
      public final boolean isInitialized() {
        return true;
      }

      @java.lang.Override
      public Builder mergeFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws java.io.IOException {
        if (extensionRegistry == null) {
          throw new java.lang.NullPointerException();
        }
        try {
          boolean done = false;
          while (!done) {
            int tag = input.readTag();
            switch (tag) {
              case 0:
                done = true;
                break;
              case 10: {
                sqlQuery_ = input.readBytes();
                bitField0_ |= 0x00000001;
                break;
              } // case 10
              default: {
                if (!super.parseUnknownField(input, extensionRegistry, tag)) {
                  done = true; // was an endgroup tag
                }
                break;
              } // default:
            } // switch (tag)
          } // while (!done)
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.unwrapIOException();
        } finally {
          onChanged();
        } // finally
        return this;
      }
      private int bitField0_;

      private java.lang.Object sqlQuery_ = "";
      /**
       * <code>optional string sql_query = 1;</code>
       * @return Whether the sqlQuery field is set.
       */
      public boolean hasSqlQuery() {
        return ((bitField0_ & 0x00000001) != 0);
      }
      /**
       * <code>optional string sql_query = 1;</code>
       * @return The sqlQuery.
       */
      public java.lang.String getSqlQuery() {
        java.lang.Object ref = sqlQuery_;
        if (!(ref instanceof java.lang.String)) {
          com.google.protobuf.ByteString bs =
              (com.google.protobuf.ByteString) ref;
          java.lang.String s = bs.toStringUtf8();
          if (bs.isValidUtf8()) {
            sqlQuery_ = s;
          }
          return s;
        } else {
          return (java.lang.String) ref;
        }
      }
      /**
       * <code>optional string sql_query = 1;</code>
       * @return The bytes for sqlQuery.
       */
      public com.google.protobuf.ByteString
          getSqlQueryBytes() {
        java.lang.Object ref = sqlQuery_;
        if (ref instanceof String) {
          com.google.protobuf.ByteString b = 
              com.google.protobuf.ByteString.copyFromUtf8(
                  (java.lang.String) ref);
          sqlQuery_ = b;
          return b;
        } else {
          return (com.google.protobuf.ByteString) ref;
        }
      }
      /**
       * <code>optional string sql_query = 1;</code>
       * @param value The sqlQuery to set.
       * @return This builder for chaining.
       */
      public Builder setSqlQuery(
          java.lang.String value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        sqlQuery_ = value;
        onChanged();
        return this;
      }
      /**
       * <code>optional string sql_query = 1;</code>
       * @return This builder for chaining.
       */
      public Builder clearSqlQuery() {
        bitField0_ = (bitField0_ & ~0x00000001);
        sqlQuery_ = getDefaultInstance().getSqlQuery();
        onChanged();
        return this;
      }
      /**
       * <code>optional string sql_query = 1;</code>
       * @param value The bytes for sqlQuery to set.
       * @return This builder for chaining.
       */
      public Builder setSqlQueryBytes(
          com.google.protobuf.ByteString value) {
        if (value == null) {
    throw new NullPointerException();
  }
  bitField0_ |= 0x00000001;
        sqlQuery_ = value;
        onChanged();
        return this;
      }
      @java.lang.Override
      public final Builder setUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.setUnknownFields(unknownFields);
      }

      @java.lang.Override
      public final Builder mergeUnknownFields(
          final com.google.protobuf.UnknownFieldSet unknownFields) {
        return super.mergeUnknownFields(unknownFields);
      }


      // @@protoc_insertion_point(builder_scope:exec.bit.ServerPreparedStatementState)
    }

    // @@protoc_insertion_point(class_scope:exec.bit.ServerPreparedStatementState)
    private static final org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState();
    }

    public static org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState getDefaultInstance() {
      return DEFAULT_INSTANCE;
    }

    @java.lang.Deprecated public static final com.google.protobuf.Parser<ServerPreparedStatementState>
        PARSER = new com.google.protobuf.AbstractParser<ServerPreparedStatementState>() {
      @java.lang.Override
      public ServerPreparedStatementState parsePartialFrom(
          com.google.protobuf.CodedInputStream input,
          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
          throws com.google.protobuf.InvalidProtocolBufferException {
        Builder builder = newBuilder();
        try {
          builder.mergeFrom(input, extensionRegistry);
        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
          throw e.setUnfinishedMessage(builder.buildPartial());
        } catch (com.google.protobuf.UninitializedMessageException e) {
          throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
        } catch (java.io.IOException e) {
          throw new com.google.protobuf.InvalidProtocolBufferException(e)
              .setUnfinishedMessage(builder.buildPartial());
        }
        return builder.buildPartial();
      }
    };

    public static com.google.protobuf.Parser<ServerPreparedStatementState> parser() {
      return PARSER;
    }

    @java.lang.Override
    public com.google.protobuf.Parser<ServerPreparedStatementState> getParserForType() {
      return PARSER;
    }

    @java.lang.Override
    public org.apache.drill.exec.proto.ExecProtos.ServerPreparedStatementState getDefaultInstanceForType() {
      return DEFAULT_INSTANCE;
    }

  }

  private static final com.google.protobuf.Descriptors.Descriptor
    internal_static_exec_bit_FragmentHandle_descriptor;
  private static final 
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
      internal_static_exec_bit_FragmentHandle_fieldAccessorTable;
  private static final com.google.protobuf.Descriptors.Descriptor
    internal_static_exec_bit_ServerPreparedStatementState_descriptor;
  private static final 
    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
      internal_static_exec_bit_ServerPreparedStatementState_fieldAccessorTable;

  public static com.google.protobuf.Descriptors.FileDescriptor
      getDescriptor() {
    return descriptor;
  }
  private static  com.google.protobuf.Descriptors.FileDescriptor
      descriptor;
  static {
    java.lang.String[] descriptorData = {
      "\n\025ExecutionProtos.proto\022\010exec.bit\032\022Coord" +
      "ination.proto\032\023UserBitShared.proto\"\235\001\n\016F" +
      "ragmentHandle\022&\n\010query_id\030\001 \001(\0132\024.exec.s" +
      "hared.QueryId\022\031\n\021major_fragment_id\030\002 \001(\005" +
      "\022\031\n\021minor_fragment_id\030\003 \001(\005\022-\n\017parent_qu" +
      "ery_id\030\004 \001(\0132\024.exec.shared.QueryId\"1\n\034Se" +
      "rverPreparedStatementState\022\021\n\tsql_query\030" +
      "\001 \001(\tB+\n\033org.apache.drill.exec.protoB\nEx" +
      "ecProtosH\001"
    };
    descriptor = com.google.protobuf.Descriptors.FileDescriptor
      .internalBuildGeneratedFileFrom(descriptorData,
        new com.google.protobuf.Descriptors.FileDescriptor[] {
          org.apache.drill.exec.proto.CoordinationProtos.getDescriptor(),
          org.apache.drill.exec.proto.UserBitShared.getDescriptor(),
        });
    internal_static_exec_bit_FragmentHandle_descriptor =
      getDescriptor().getMessageTypes().get(0);
    internal_static_exec_bit_FragmentHandle_fieldAccessorTable = new
      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
        internal_static_exec_bit_FragmentHandle_descriptor,
        new java.lang.String[] { "QueryId", "MajorFragmentId", "MinorFragmentId", "ParentQueryId", });
    internal_static_exec_bit_ServerPreparedStatementState_descriptor =
      getDescriptor().getMessageTypes().get(1);
    internal_static_exec_bit_ServerPreparedStatementState_fieldAccessorTable = new
      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
        internal_static_exec_bit_ServerPreparedStatementState_descriptor,
        new java.lang.String[] { "SqlQuery", });
    org.apache.drill.exec.proto.CoordinationProtos.getDescriptor();
    org.apache.drill.exec.proto.UserBitShared.getDescriptor();
  }

  // @@protoc_insertion_point(outer_class_scope)
}
