@Test
  public void testFixedType() {
    // Build a required uint field definition
    MajorType.Builder typeBuilder = MajorType.newBuilder();
    FieldDef.Builder defBuilder = FieldDef.newBuilder();
    typeBuilder.setMinorType(MinorType.UINT4).setMode(DataMode.REQUIRED).setWidth(4);
    defBuilder.setMajorType(typeBuilder.build());
    MaterializedField field = MaterializedField.create(defBuilder.build());

    // Create a new value vector for 1024 integers
    UInt4Vector v = new UInt4Vector(field, allocator);
    UInt4Vector.Mutator m = v.getMutator();
    v.allocateNew(1024);

    // Put and set a few values
    m.set(0, 100);
    m.set(1, 101);
    m.set(100, 102);
    m.set(1022, 103);
    m.set(1023, 104);
    assertEquals(100, v.getAccessor().get(0));
    assertEquals(101, v.getAccessor().get(1));
    assertEquals(102, v.getAccessor().get(100));
    assertEquals(103, v.getAccessor().get(1022));
    assertEquals(104, v.getAccessor().get(1023));

    // Ensure unallocated space returns 0
    assertEquals(0, v.getAccessor().get(3));
  }
    // The output table's column names always follow the left table,
    // where the output type is chosen based on DRILL's implicit casting rules
    private void inferOutputFields() {
      outputFields = Lists.newArrayList();
      leftSchema = leftSide.getRecordBatch().getSchema();
      rightSchema = rightSide.getRecordBatch().getSchema();
      Iterator<MaterializedField> leftIter = leftSchema.iterator();
      Iterator<MaterializedField> rightIter = rightSchema.iterator();

      int index = 1;
      while (leftIter.hasNext() && rightIter.hasNext()) {
        MaterializedField leftField = leftIter.next();
        MaterializedField rightField = rightIter.next();

        if (hasSameTypeAndMode(leftField, rightField)) {
          outputFields.add(MaterializedField.create(leftField.getPath(), leftField.getType()));
        } else {
          // If the output type is not the same,
          // cast the column of one of the table to a data type which is the Least Restrictive
          MinorType outputMinorType;
          if (leftField.getType().getMinorType() == rightField.getType().getMinorType()) {
            outputMinorType = leftField.getType().getMinorType();
          } else {
            List<MinorType> types = Lists.newLinkedList();
            types.add(leftField.getType().getMinorType());
            types.add(rightField.getType().getMinorType());
            outputMinorType = TypeCastRules.getLeastRestrictiveType(types);
            if (outputMinorType == null) {
              throw new DrillRuntimeException(
                  "Type mismatch between "
                      + leftField.getType().getMinorType().toString()
                      + " on the left side and "
                      + rightField.getType().getMinorType().toString()
                      + " on the right side in column "
                      + index
                      + " of UNION ALL");
            }
          }

          // The output data mode should be as flexible as the more flexible one from the two input
          // tables
          List<DataMode> dataModes = Lists.newLinkedList();
          dataModes.add(leftField.getType().getMode());
          dataModes.add(rightField.getType().getMode());
          DataMode dataMode = TypeCastRules.getLeastRestrictiveDataMode(dataModes);

          MajorType.Builder builder = MajorType.newBuilder();
          builder.setMinorType(outputMinorType);
          builder.setMode(dataMode);
          outputFields.add(MaterializedField.create(leftField.getPath(), builder.build()));
        }
        ++index;
      }

      assert !leftIter.hasNext() && !rightIter.hasNext()
          : "Mis-match of column count should have been detected when validating sqlNode at planning";
    }
  @Test
  public void testNullableFloat() {
    // Build an optional float field definition
    MajorType.Builder typeBuilder = MajorType.newBuilder();
    FieldDef.Builder defBuilder = FieldDef.newBuilder();
    typeBuilder.setMinorType(MinorType.FLOAT4).setMode(DataMode.OPTIONAL).setWidth(4);
    defBuilder.setMajorType(typeBuilder.build());
    MaterializedField field = MaterializedField.create(defBuilder.build());

    // Create a new value vector for 1024 integers
    NullableFloat4Vector v = (NullableFloat4Vector) TypeHelper.getNewVector(field, allocator);
    NullableFloat4Vector.Mutator m = v.getMutator();
    v.allocateNew(1024);

    // Put and set a few values
    m.set(0, 100.1f);
    m.set(1, 101.2f);
    m.set(100, 102.3f);
    m.set(1022, 103.4f);
    m.set(1023, 104.5f);
    assertEquals(100.1f, v.getAccessor().get(0), 0);
    assertEquals(101.2f, v.getAccessor().get(1), 0);
    assertEquals(102.3f, v.getAccessor().get(100), 0);
    assertEquals(103.4f, v.getAccessor().get(1022), 0);
    assertEquals(104.5f, v.getAccessor().get(1023), 0);

    // Ensure null values throw
    {
      boolean b = false;
      try {
        v.getAccessor().get(3);
      } catch (AssertionError e) {
        b = true;
      } finally {
        if (!b) {
          assert false;
        }
      }
    }

    v.allocateNew(2048);
    {
      boolean b = false;
      try {
        v.getAccessor().get(0);
      } catch (AssertionError e) {
        b = true;
      } finally {
        if (!b) {
          assert false;
        }
      }
    }
  }
  /**
   * Returns the merger of schemas. The merged schema will include the union all columns. If there
   * is a type conflict between columns with the same schemapath but different types, the merged
   * schema will contain a Union type.
   *
   * @param schemas
   * @return
   */
  public static BatchSchema mergeSchemas(BatchSchema... schemas) {
    Map<SchemaPath, Set<MinorType>> typeSetMap = Maps.newLinkedHashMap();

    for (BatchSchema s : schemas) {
      for (MaterializedField field : s) {
        SchemaPath path = field.getPath();
        Set<MinorType> currentTypes = typeSetMap.get(path);
        if (currentTypes == null) {
          currentTypes = Sets.newHashSet();
          typeSetMap.put(path, currentTypes);
        }
        MinorType newType = field.getType().getMinorType();
        if (newType == MinorType.MAP || newType == MinorType.LIST) {
          throw new RuntimeException(
              "Schema change not currently supported for schemas with complex types");
        }
        if (newType == MinorType.UNION) {
          for (MinorType subType : field.getType().getSubTypeList()) {
            currentTypes.add(subType);
          }
        } else {
          currentTypes.add(newType);
        }
      }
    }

    List<MaterializedField> fields = Lists.newArrayList();

    for (SchemaPath path : typeSetMap.keySet()) {
      Set<MinorType> types = typeSetMap.get(path);
      if (types.size() > 1) {
        MajorType.Builder builder =
            MajorType.newBuilder().setMinorType(MinorType.UNION).setMode(DataMode.OPTIONAL);
        for (MinorType t : types) {
          builder.addSubType(t);
        }
        MaterializedField field = MaterializedField.create(path, builder.build());
        fields.add(field);
      } else {
        MaterializedField field =
            MaterializedField.create(path, Types.optional(types.iterator().next()));
        fields.add(field);
      }
    }

    SchemaBuilder schemaBuilder = new SchemaBuilder();
    BatchSchema s =
        schemaBuilder
            .addFields(fields)
            .setSelectionVectorMode(schemas[0].getSelectionVectorMode())
            .build();
    return s;
  }
  @Test
  public void testBitVector() {
    // Build a required boolean field definition
    MajorType.Builder typeBuilder = MajorType.newBuilder();
    FieldDef.Builder defBuilder = FieldDef.newBuilder();
    typeBuilder.setMinorType(MinorType.BIT).setMode(DataMode.REQUIRED).setWidth(4);
    defBuilder.setMajorType(typeBuilder.build());
    MaterializedField field = MaterializedField.create(defBuilder.build());

    // Create a new value vector for 1024 integers
    BitVector v = new BitVector(field, allocator);
    BitVector.Mutator m = v.getMutator();
    v.allocateNew(1024);

    // Put and set a few values
    m.set(0, 1);
    m.set(1, 0);
    m.set(100, 0);
    m.set(1022, 1);
    assertEquals(1, v.getAccessor().get(0));
    assertEquals(0, v.getAccessor().get(1));
    assertEquals(0, v.getAccessor().get(100));
    assertEquals(1, v.getAccessor().get(1022));

    // test setting the same value twice
    m.set(0, 1);
    m.set(0, 1);
    m.set(1, 0);
    m.set(1, 0);
    assertEquals(1, v.getAccessor().get(0));
    assertEquals(0, v.getAccessor().get(1));

    // test toggling the values
    m.set(0, 0);
    m.set(1, 1);
    assertEquals(0, v.getAccessor().get(0));
    assertEquals(1, v.getAccessor().get(1));

    // Ensure unallocated space returns 0
    assertEquals(0, v.getAccessor().get(3));
  }
 @JsonIgnore
 public MajorType getMajorType() {
   MajorType.Builder b = MajorType.newBuilder();
   b.setMode(mode);
   b.setMinorType(minorType);
   if (precision != null) b.setPrecision(precision);
   if (width != null) b.setWidth(width);
   if (scale != null) b.setScale(scale);
   return b.build();
 }
  @Test
  public void testNullableVarLen2() {
    // Build an optional varchar field definition
    MajorType.Builder typeBuilder = MajorType.newBuilder();
    FieldDef.Builder defBuilder = FieldDef.newBuilder();
    typeBuilder.setMinorType(MinorType.VARCHAR).setMode(DataMode.OPTIONAL).setWidth(2);
    defBuilder.setMajorType(typeBuilder.build());
    MaterializedField field = MaterializedField.create(defBuilder.build());

    // Create a new value vector for 1024 integers
    NullableVarCharVector v = new NullableVarCharVector(field, allocator);
    NullableVarCharVector.Mutator m = v.getMutator();
    v.allocateNew(1024 * 10, 1024);

    // Create and set 3 sample strings
    String str1 = new String("AAAAA1");
    String str2 = new String("BBBBBBBBB2");
    String str3 = new String("CCCC3");
    m.set(0, str1.getBytes(Charset.forName("UTF-8")));
    m.set(1, str2.getBytes(Charset.forName("UTF-8")));
    m.set(2, str3.getBytes(Charset.forName("UTF-8")));

    // Check the sample strings
    assertEquals(str1, new String(v.getAccessor().get(0), Charset.forName("UTF-8")));
    assertEquals(str2, new String(v.getAccessor().get(1), Charset.forName("UTF-8")));
    assertEquals(str3, new String(v.getAccessor().get(2), Charset.forName("UTF-8")));

    // Ensure null value throws
    boolean b = false;
    try {
      v.getAccessor().get(3);
    } catch (AssertionError e) {
      b = true;
    } finally {
      if (!b) {
        assert false;
      }
    }
  }
  @Test
  public void testNullableFixedType() {
    // Build an optional uint field definition
    MajorType.Builder typeBuilder = MajorType.newBuilder();
    FieldDef.Builder defBuilder = FieldDef.newBuilder();
    typeBuilder.setMinorType(MinorType.UINT4).setMode(DataMode.OPTIONAL).setWidth(4);
    defBuilder.setMajorType(typeBuilder.build());
    MaterializedField field = MaterializedField.create(defBuilder.build());

    // Create a new value vector for 1024 integers
    NullableUInt4Vector v = new NullableUInt4Vector(field, allocator);
    NullableUInt4Vector.Mutator m = v.getMutator();
    v.allocateNew(1024);

    // Put and set a few values
    m.set(0, 100);
    m.set(1, 101);
    m.set(100, 102);
    m.set(1022, 103);
    m.set(1023, 104);
    assertEquals(100, v.getAccessor().get(0));
    assertEquals(101, v.getAccessor().get(1));
    assertEquals(102, v.getAccessor().get(100));
    assertEquals(103, v.getAccessor().get(1022));
    assertEquals(104, v.getAccessor().get(1023));

    // Ensure null values throw
    {
      boolean b = false;
      try {
        v.getAccessor().get(3);
      } catch (AssertionError e) {
        b = true;
      } finally {
        if (!b) {
          assert false;
        }
      }
    }

    v.allocateNew(2048);
    {
      boolean b = false;
      try {
        v.getAccessor().get(0);
      } catch (AssertionError e) {
        b = true;
      } finally {
        if (!b) {
          assert false;
        }
      }
    }

    m.set(0, 100);
    m.set(1, 101);
    m.set(100, 102);
    m.set(1022, 103);
    m.set(1023, 104);
    assertEquals(100, v.getAccessor().get(0));
    assertEquals(101, v.getAccessor().get(1));
    assertEquals(102, v.getAccessor().get(100));
    assertEquals(103, v.getAccessor().get(1022));
    assertEquals(104, v.getAccessor().get(1023));

    // Ensure null values throw

    {
      boolean b = false;
      try {
        v.getAccessor().get(3);
      } catch (AssertionError e) {
        b = true;
      } finally {
        if (!b) {
          assert false;
        }
      }
    }
  }