@Test
  public void testArrayPrependFunction11() throws Exception {
    Object[] o =
        new Object[] {
          BigDecimal.valueOf(2345), BigDecimal.valueOf(-23.45), BigDecimal.valueOf(785)
        };
    Object[] o2 =
        new Object[] {
          BigDecimal.valueOf(-19),
          BigDecimal.valueOf(2345),
          BigDecimal.valueOf(-23.45),
          BigDecimal.valueOf(785)
        };
    Object element = BigDecimal.valueOf(-19);
    PDataType baseType = PDecimal.INSTANCE;

    PhoenixArray arr = new PhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray(baseType, o2);
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        null,
        null,
        baseType,
        null,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.ASC);
  }
  @Test
  public void testForNullsWith509NullsAtBeginning() throws Exception {
    // 509 nulls at the beginning
    Object[] o = new Object[511];
    for (int i = 0; i < o.length - 2; i++) o[i] = null;

    o[o.length - 2] = "1";
    o[o.length - 1] = "2";

    Object[] o2 = new Object[512];
    for (int i = 0; i < o2.length - 2; i++) o2[i] = null;

    o2[o2.length - 2] = "1";
    o2[o2.length - 1] = "2";

    Object element = null;
    PDataType baseType = PVarchar.INSTANCE;

    PhoenixArray arr = new PhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray(baseType, o2);
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        null,
        null,
        baseType,
        1,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.DESC);
  }
  @Test
  public void testArrayPrependFunction14() throws Exception {
    Calendar calendar = Calendar.getInstance();
    java.util.Date currentDate = calendar.getTime();
    java.sql.Timestamp timestamp = new java.sql.Timestamp(currentDate.getTime());

    Object[] o = new Object[] {timestamp, timestamp, timestamp};
    Object[] o2 = new Object[] {timestamp, timestamp, timestamp, timestamp};
    PDataType baseType = PTimestamp.INSTANCE;

    PhoenixArray arr = new PhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray(baseType, o2);
    test(
        arr,
        timestamp,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        null,
        null,
        baseType,
        null,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.ASC);
  }
  @Test
  public void testArrayPrependFunction6() throws Exception {
    Object[] o = new Object[] {new Float(2.3), new Float(7.9), new Float(-9.6), new Float(2.3)};
    Object[] o2 =
        new Object[] {
          new Float(8.9), new Float(2.3), new Float(7.9), new Float(-9.6), new Float(2.3)
        };
    Object element = 8.9;
    PDataType baseType = PFloat.INSTANCE;

    PhoenixArray arr = new PhoenixArray.PrimitiveFloatPhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray.PrimitiveFloatPhoenixArray(baseType, o2);
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        null,
        null,
        baseType,
        null,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.ASC);
  }
  @Test
  public void testArrayPrependFunction4() throws Exception {
    // offset array int
    Object[] o = new Object[Short.MAX_VALUE + 7];
    for (int i = 0; i < o.length; i++) {
      o[i] = "a";
    }
    Object[] o2 = new Object[Short.MAX_VALUE + 8];
    for (int i = 1; i < o2.length; i++) {
      o2[i] = "a";
    }
    Object element = "b";
    o2[0] = element;
    PDataType baseType = PVarchar.INSTANCE;

    PhoenixArray arr = new PhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray(baseType, o2);
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        null,
        null,
        baseType,
        null,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.ASC);
  }
  @Test
  public void testForNullsAllNulls() throws Exception {
    Object element = null;
    PDataType baseType = PChar.INSTANCE;

    PhoenixArray arr = null;
    PhoenixArray expected = null;
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        4,
        null,
        baseType,
        1,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.DESC);
  }
  @Test
  public void testForNullsWithNullsInMiddle() throws Exception {
    Object[] o = new Object[] {"1   ", "2   ", null, "3   ", "4   "};
    Object[] o2 = new Object[] {null, "1   ", "2   ", null, "3   ", "4   "};
    Object element = null;
    PDataType baseType = PVarchar.INSTANCE;

    PhoenixArray arr = new PhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray(baseType, o2);
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        null,
        null,
        baseType,
        1,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.DESC);
  }
  @Test
  public void testArrayPrependFunction1() throws Exception {
    Object[] o = new Object[] {1, 2, -3, 4};
    Object[] o2 = new Object[] {5, 1, 2, -3, 4};
    Object element = 5;
    PDataType baseType = PInteger.INSTANCE;

    PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray.PrimitiveIntPhoenixArray(baseType, o2);
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        null,
        null,
        baseType,
        null,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.ASC);
  }
  @Test
  public void testArrayPrependFunction21() throws Exception {
    Object[] o = new Object[] {4.78, 9.54, 2.34, -9.675, Double.MAX_VALUE};
    Object[] o2 = new Object[] {12.67, 4.78, 9.54, 2.34, -9.675, Double.MAX_VALUE};
    Object element = 12.67;
    PDataType baseType = PDouble.INSTANCE;

    PhoenixArray arr = new PhoenixArray.PrimitiveDoublePhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray.PrimitiveDoublePhoenixArray(baseType, o2);
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        null,
        null,
        baseType,
        null,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.DESC);
  }
  @Test
  public void testArrayPrependFunction20() throws Exception {
    Object[] o = new Object[] {"1   ", "2   ", "3   ", "4   "};
    Object[] o2 = new Object[] {"5", "1", "2", "3", "4"};
    Object element = "5";
    PDataType baseType = PChar.INSTANCE;

    PhoenixArray arr = new PhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray(baseType, o2);
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        4,
        null,
        baseType,
        1,
        null,
        expected,
        SortOrder.DESC,
        SortOrder.DESC);
  }
  @Test
  public void testArrayPrependFunction10() throws Exception {
    Object[] o = new Object[] {(byte) 4, (byte) 8, (byte) 9};
    Object[] o2 = new Object[] {(byte) 6, (byte) 4, (byte) 8, (byte) 9};
    Object element = (byte) 6;
    PDataType baseType = PTinyint.INSTANCE;

    PhoenixArray arr = new PhoenixArray.PrimitiveBytePhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray.PrimitiveBytePhoenixArray(baseType, o2);
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        null,
        null,
        baseType,
        null,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.ASC);
  }
  @Test
  public void testArrayPrependFunction8() throws Exception {
    Object[] o = new Object[] {123l, 677l, 98789l, -78989l, 66787l};
    Object[] o2 = new Object[] {543l, 123l, 677l, 98789l, -78989l, 66787l};
    Object element = 543l;
    PDataType baseType = PLong.INSTANCE;

    PhoenixArray arr = new PhoenixArray.PrimitiveLongPhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray.PrimitiveLongPhoenixArray(baseType, o2);
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        null,
        null,
        baseType,
        null,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.ASC);
  }
  @Test
  public void testArrayPrependFunctionBoolean() throws Exception {
    Boolean[] o = new Boolean[] {true, false, false, true};
    Boolean[] o2 = new Boolean[] {false, true, false, false, true};
    Boolean element = false;
    PDataType baseType = PBoolean.INSTANCE;

    PhoenixArray arr = new PhoenixArray.PrimitiveBooleanPhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray.PrimitiveBooleanPhoenixArray(baseType, o2);
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        null,
        null,
        baseType,
        null,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.ASC);
  }
  @Test
  public void testArrayPrependFunction9() throws Exception {
    Object[] o = new Object[] {(short) 34, (short) -23, (short) -89, (short) 999, (short) 34};
    Object[] o2 =
        new Object[] {(short) 7, (short) 34, (short) -23, (short) -89, (short) 999, (short) 34};
    Object element = (short) 7;
    PDataType baseType = PSmallint.INSTANCE;

    PhoenixArray arr = new PhoenixArray.PrimitiveShortPhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray.PrimitiveShortPhoenixArray(baseType, o2);
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        null,
        null,
        baseType,
        null,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.ASC);
  }
  @Test
  public void testArrayPrependFunction24() throws Exception {
    byte[][] o =
        new byte[][] {
          new byte[] {2, 0},
          new byte[] {13, 3},
          new byte[] {5, 3},
          new byte[] {6, 3},
          new byte[] {2, 5}
        };
    byte[][] o2 =
        new byte[][] {
          new byte[] {5, 6},
          new byte[] {2, 0},
          new byte[] {13, 3},
          new byte[] {5, 3},
          new byte[] {6, 3},
          new byte[] {2, 5}
        };
    byte[] element = new byte[] {5, 6};
    PDataType baseType = PBinary.INSTANCE;

    PhoenixArray arr = new PhoenixArray(baseType, o);
    PhoenixArray expected = new PhoenixArray(baseType, o2);
    test(
        arr,
        element,
        PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
        3,
        null,
        baseType,
        1,
        null,
        expected,
        SortOrder.ASC,
        SortOrder.DESC);
  }
  @Override
  public void upsertEvents(List<Event> events) throws SQLException {
    Preconditions.checkNotNull(events);
    Preconditions.checkNotNull(connection);
    Preconditions.checkNotNull(this.upsertStatement);

    boolean wasAutoCommit = connection.getAutoCommit();
    connection.setAutoCommit(false);
    try (PreparedStatement colUpsert = connection.prepareStatement(upsertStatement)) {
      String value = null;
      Integer sqlType = null;
      for (Event event : events) {
        byte[] payloadBytes = event.getBody();
        if (payloadBytes == null || payloadBytes.length == 0) {
          continue;
        }
        String payload = new String(payloadBytes);
        Matcher m = inputPattern.matcher(payload.trim());

        if (!m.matches()) {
          logger.debug(
              "payload {} doesn't match the pattern {} ", payload, inputPattern.toString());
          continue;
        }
        if (m.groupCount() != colNames.size()) {
          logger.debug(
              "payload {} size doesn't match the pattern {} ", m.groupCount(), colNames.size());
          continue;
        }
        int index = 1;
        int offset = 0;
        for (int i = 0; i < colNames.size(); i++, offset++) {
          if (columnMetadata[offset] == null) {
            continue;
          }

          value = m.group(i + 1);
          sqlType = columnMetadata[offset].getSqlType();
          Object upsertValue = PDataType.fromTypeId(sqlType).toObject(value);
          if (upsertValue != null) {
            colUpsert.setObject(index++, upsertValue, sqlType);
          } else {
            colUpsert.setNull(index++, sqlType);
          }
        }

        // add headers if necessary
        Map<String, String> headerValues = event.getHeaders();
        for (int i = 0; i < headers.size(); i++, offset++) {

          String headerName = headers.get(i);
          String headerValue = headerValues.get(headerName);
          sqlType = columnMetadata[offset].getSqlType();
          Object upsertValue = PDataType.fromTypeId(sqlType).toObject(headerValue);
          if (upsertValue != null) {
            colUpsert.setObject(index++, upsertValue, sqlType);
          } else {
            colUpsert.setNull(index++, sqlType);
          }
        }

        if (autoGenerateKey) {
          sqlType = columnMetadata[offset].getSqlType();
          String generatedRowValue = this.keyGenerator.generate();
          Object rowkeyValue = PDataType.fromTypeId(sqlType).toObject(generatedRowValue);
          colUpsert.setObject(index++, rowkeyValue, sqlType);
        }
        colUpsert.execute();
      }
      connection.commit();
    } catch (Exception ex) {
      logger.error("An error {} occurred during persisting the event ", ex.getMessage());
      throw new SQLException(ex.getMessage());
    } finally {
      if (wasAutoCommit) {
        connection.setAutoCommit(true);
      }
    }
  }