/**
 * This runtime function checks if the input is null. If the input is not null, just return it
 * directly; Otherwise, throw a runtime exception.
 */
public class NotNullDescriptor extends AbstractScalarFunctionDynamicDescriptor {

  private static final long serialVersionUID = 1L;
  public static final IFunctionDescriptorFactory FACTORY =
      new IFunctionDescriptorFactory() {
        public IFunctionDescriptor createFunctionDescriptor() {
          return new NotNullDescriptor();
        }
      };
  private static final byte SER_NULL_TYPE_TAG = ATypeTag.NULL.serialize();

  @Override
  public ICopyEvaluatorFactory createEvaluatorFactory(final ICopyEvaluatorFactory[] args) {
    return new ICopyEvaluatorFactory() {
      private static final long serialVersionUID = 1L;

      @Override
      public ICopyEvaluator createEvaluator(final IDataOutputProvider output)
          throws AlgebricksException {
        return new ICopyEvaluator() {
          private DataOutput out = output.getDataOutput();
          private ArrayBackedValueStorage outInput = new ArrayBackedValueStorage();
          private ICopyEvaluator eval = args[0].createEvaluator(outInput);
          private String errorMessage =
              AsterixBuiltinFunctions.NOT_NULL + ": the input value cannot be NULL.";

          @Override
          public void evaluate(IFrameTupleReference tuple) throws AlgebricksException {

            try {
              outInput.reset();
              eval.evaluate(tuple);
              byte[] data = outInput.getByteArray();
              if (data[outInput.getStartOffset()] == SER_NULL_TYPE_TAG) {
                throw new AlgebricksException(errorMessage);
              }
              out.write(data, outInput.getStartOffset(), outInput.getLength());
            } catch (IOException e1) {
              throw new AlgebricksException(errorMessage);
            }
          }
        };
      }
    };
  }

  @Override
  public FunctionIdentifier getIdentifier() {
    return AsterixBuiltinFunctions.NOT_NULL;
  }
}
 protected void finishPartialResults() throws AlgebricksException {
   try {
     // Double check that count 0 is accounted
     if (aggType == ATypeTag.SYSTEM_NULL) {
       if (GlobalConfig.DEBUG) {
         GlobalConfig.ASTERIX_LOGGER.finest("AVG aggregate ran over empty input.");
       }
       out.writeByte(ATypeTag.SYSTEM_NULL.serialize());
     } else if (aggType == ATypeTag.NULL) {
       out.writeByte(ATypeTag.NULL.serialize());
     } else {
       sumBytes.reset();
       aDouble.setValue(sum);
       doubleSerde.serialize(aDouble, sumBytesOutput);
       countBytes.reset();
       aInt64.setValue(count);
       longSerde.serialize(aInt64, countBytesOutput);
       recordEval.evaluate(null);
     }
   } catch (IOException e) {
     throw new AlgebricksException(e);
   }
 }
public abstract class AbstractTripleStringStringEval implements ICopyEvaluator {

  private DataOutput dout;
  private static final byte SER_NULL_TYPE_TAG = ATypeTag.NULL.serialize();
  private static final byte SER_STRING_TYPE_TAG = ATypeTag.STRING.serialize();
  private ArrayBackedValueStorage array0 = new ArrayBackedValueStorage();
  private ArrayBackedValueStorage array1 = new ArrayBackedValueStorage();
  private ArrayBackedValueStorage array2 = new ArrayBackedValueStorage();
  private ICopyEvaluator eval0;
  private ICopyEvaluator eval1;
  private ICopyEvaluator eval2;

  private AMutableString resultBuffer = new AMutableString("");

  @SuppressWarnings("rawtypes")
  private ISerializerDeserializer nullSerde =
      AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);

  @SuppressWarnings("rawtypes")
  private ISerializerDeserializer strSerde =
      AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ASTRING);

  private final UTF8StringPointable strPtr1st = new UTF8StringPointable();
  private final UTF8StringPointable strPtr2nd = new UTF8StringPointable();
  private final UTF8StringPointable strPtr3rd = new UTF8StringPointable();

  private final FunctionIdentifier funcID;

  public AbstractTripleStringStringEval(
      DataOutput dout,
      ICopyEvaluatorFactory eval0,
      ICopyEvaluatorFactory eval1,
      ICopyEvaluatorFactory eval2,
      FunctionIdentifier funcID)
      throws AlgebricksException {
    this.dout = dout;
    this.eval0 = eval0.createEvaluator(array0);
    this.eval1 = eval1.createEvaluator(array1);
    this.eval2 = eval2.createEvaluator(array2);
    this.funcID = funcID;
  }

  @SuppressWarnings("unchecked")
  @Override
  public void evaluate(IFrameTupleReference tuple) throws AlgebricksException {
    array0.reset();
    eval0.evaluate(tuple);
    array1.reset();
    eval1.evaluate(tuple);
    array2.reset();
    eval2.evaluate(tuple);

    try {
      if (array0.getByteArray()[0] == SER_NULL_TYPE_TAG
          || array1.getByteArray()[0] == SER_NULL_TYPE_TAG
          || array2.getByteArray()[0] == SER_NULL_TYPE_TAG) {
        nullSerde.serialize(ANull.NULL, dout);
        return;
      } else if (array0.getByteArray()[0] != SER_STRING_TYPE_TAG
          || array1.getByteArray()[0] != SER_STRING_TYPE_TAG
          || array2.getByteArray()[0] != SER_STRING_TYPE_TAG) {
        throw new AlgebricksException(
            funcID.getName()
                + ": expects input type (STRING/NULL, STRING/NULL, STRING/NULL), but got ("
                + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(array0.getByteArray()[0])
                + ", "
                + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(array1.getByteArray()[0])
                + ", "
                + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(array2.getByteArray()[0])
                + ".");
      }
    } catch (HyracksDataException e) {
      throw new AlgebricksException(e);
    }

    strPtr1st.set(array0.getByteArray(), array0.getStartOffset() + 1, array0.getLength());
    strPtr2nd.set(array1.getByteArray(), array1.getStartOffset() + 1, array1.getLength());
    strPtr3rd.set(array2.getByteArray(), array2.getStartOffset() + 1, array2.getLength());

    String res = compute(strPtr1st, strPtr2nd, strPtr3rd);
    resultBuffer.setValue(res);
    try {
      strSerde.serialize(resultBuffer, dout);
    } catch (HyracksDataException e) {
      throw new AlgebricksException(e);
    }
  }

  protected abstract String compute(
      UTF8StringPointable strPtr1st, UTF8StringPointable strPtr2nd, UTF8StringPointable strPtr3rd)
      throws AlgebricksException;
}
public class ParseTimeDescriptor extends AbstractScalarFunctionDynamicDescriptor {

  private static final long serialVersionUID = 1L;
  public static final FunctionIdentifier FID = AsterixBuiltinFunctions.PARSE_TIME;

  private static final byte SER_STRING_TYPE_TAG = ATypeTag.STRING.serialize();
  private static final byte SER_NULL_TYPE_TAG = ATypeTag.NULL.serialize();
  private static final DateTimeFormatUtils DT_UTILS = DateTimeFormatUtils.getInstance();

  public static final IFunctionDescriptorFactory FACTORY =
      new IFunctionDescriptorFactory() {

        @Override
        public IFunctionDescriptor createFunctionDescriptor() {
          return new ParseTimeDescriptor();
        }
      };

  @Override
  public ICopyEvaluatorFactory createEvaluatorFactory(final ICopyEvaluatorFactory[] args)
      throws AlgebricksException {
    return new ICopyEvaluatorFactory() {

      private static final long serialVersionUID = 1L;

      @Override
      public ICopyEvaluator createEvaluator(final IDataOutputProvider output)
          throws AlgebricksException {
        return new ICopyEvaluator() {

          private DataOutput out = output.getDataOutput();
          private ArrayBackedValueStorage argOut0 = new ArrayBackedValueStorage();
          private ArrayBackedValueStorage argOut1 = new ArrayBackedValueStorage();
          private ICopyEvaluator eval0 = args[0].createEvaluator(argOut0);
          private ICopyEvaluator eval1 = args[1].createEvaluator(argOut1);

          @SuppressWarnings("unchecked")
          private ISerializerDeserializer<ANull> nullSerde =
              AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(
                  BuiltinType.ANULL);

          @SuppressWarnings("unchecked")
          private ISerializerDeserializer<ATime> timeSerde =
              AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(
                  BuiltinType.ATIME);

          private AMutableTime aTime = new AMutableTime(0);
          private final UTF8StringPointable utf8Ptr = new UTF8StringPointable();

          @Override
          public void evaluate(IFrameTupleReference tuple) throws AlgebricksException {
            argOut0.reset();
            eval0.evaluate(tuple);
            argOut1.reset();
            eval1.evaluate(tuple);

            try {
              if (argOut0.getByteArray()[0] == SER_NULL_TYPE_TAG
                  || argOut1.getByteArray()[0] == SER_NULL_TYPE_TAG) {
                nullSerde.serialize(ANull.NULL, out);
                return;
              }

              if (argOut0.getByteArray()[0] != SER_STRING_TYPE_TAG
                  || argOut1.getByteArray()[0] != SER_STRING_TYPE_TAG) {
                throw new AlgebricksException(
                    getIdentifier().getName()
                        + ": expects two strings but got  ("
                        + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(
                            argOut0.getByteArray()[0])
                        + ", "
                        + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(
                            argOut1.getByteArray()[0])
                        + ")");
              }
              utf8Ptr.set(argOut0.getByteArray(), 1, argOut0.getLength() - 1);
              int start0 = utf8Ptr.getCharStartOffset();
              int length0 = utf8Ptr.getUTF8Length();

              utf8Ptr.set(argOut1.getByteArray(), 1, argOut1.getLength() - 1);
              int start1 = utf8Ptr.getCharStartOffset();
              int length1 = utf8Ptr.getUTF8Length();
              long chronon = 0;

              int formatStart = start1;
              int formatLength = 0;
              boolean processSuccessfully = false;
              while (!processSuccessfully && formatStart < start1 + length1) {
                // search for "|"
                formatLength = 0;
                for (; formatStart + formatLength < start1 + length1; formatLength++) {
                  if (argOut1.getByteArray()[formatStart + formatLength] == '|') {
                    break;
                  }
                }
                try {
                  chronon =
                      DT_UTILS.parseDateTime(
                          argOut0.getByteArray(),
                          start0,
                          length0,
                          argOut1.getByteArray(),
                          formatStart,
                          formatLength,
                          DateTimeParseMode.TIME_ONLY);
                } catch (AsterixTemporalTypeParseException ex) {
                  formatStart += formatLength + 1;
                  continue;
                }
                processSuccessfully = true;
              }

              if (!processSuccessfully) {
                throw new HyracksDataException(
                    "parse-date: Failed to match with any given format string!");
              }

              aTime.setValue((int) chronon);
              timeSerde.serialize(aTime, out);

            } catch (HyracksDataException ex) {
              throw new AlgebricksException(ex);
            }
          }
        };
      }
    };
  }

  /* (non-Javadoc)
   * @see org.apache.asterix.om.functions.AbstractFunctionDescriptor#getIdentifier()
   */
  @Override
  public FunctionIdentifier getIdentifier() {
    return FID;
  }
}
public class StringUpperCaseDescriptor extends AbstractScalarFunctionDynamicDescriptor {
  private static final long serialVersionUID = 1L;

  public static final IFunctionDescriptorFactory FACTORY =
      new IFunctionDescriptorFactory() {
        public IFunctionDescriptor createFunctionDescriptor() {
          return new StringUpperCaseDescriptor();
        }
      };
  private static final byte SER_STRING_TYPE_TAG = ATypeTag.STRING.serialize();
  private static final byte SER_NULL_TYPE_TAG = ATypeTag.NULL.serialize();

  @Override
  public ICopyEvaluatorFactory createEvaluatorFactory(final ICopyEvaluatorFactory[] args) {
    return new ICopyEvaluatorFactory() {
      private static final long serialVersionUID = 1L;

      @Override
      public ICopyEvaluator createEvaluator(final IDataOutputProvider output)
          throws AlgebricksException {
        return new ICopyEvaluator() {

          private DataOutput out = output.getDataOutput();
          private ArrayBackedValueStorage outInput = new ArrayBackedValueStorage();
          private ICopyEvaluator eval = args[0].createEvaluator(outInput);

          private final byte stt = ATypeTag.STRING.serialize();

          private final GrowableArray array = new GrowableArray();
          private final UTF8StringBuilder builder = new UTF8StringBuilder();
          private final UTF8StringPointable string = new UTF8StringPointable();

          @SuppressWarnings("unchecked")
          private ISerializerDeserializer<ANull> nullSerde =
              AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(
                  BuiltinType.ANULL);

          @Override
          public void evaluate(IFrameTupleReference tuple) throws AlgebricksException {

            try {
              outInput.reset();
              eval.evaluate(tuple);
              byte[] serString = outInput.getByteArray();

              if (serString[0] == SER_STRING_TYPE_TAG) {
                string.set(serString, 1, serString.length);
                array.reset();
                UTF8StringPointable.uppercase(string, builder, array);

                out.writeByte(stt);
                out.write(array.getByteArray(), 0, array.getLength());
              } else if (serString[0] == SER_NULL_TYPE_TAG) nullSerde.serialize(ANull.NULL, out);
              else
                throw new AlgebricksException(
                    AsterixBuiltinFunctions.STRING_UPPERCASE.getName()
                        + ": expects input type STRING/NULL but got "
                        + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serString[0]));
            } catch (IOException e1) {
              throw new AlgebricksException(e1);
            }
          }
        };
      }
    };
  }

  @Override
  public FunctionIdentifier getIdentifier() {
    return AsterixBuiltinFunctions.STRING_UPPERCASE;
  }
}
/**
 * Creates new Matcher and Pattern objects each time the value of the pattern argument (the second
 * argument) changes.
 */
public class RegExpDescriptor extends AbstractScalarFunctionDynamicDescriptor {

  private static final long serialVersionUID = 1L;

  // allowed input types
  private static final byte SER_NULL_TYPE_TAG = ATypeTag.NULL.serialize();
  private static final byte SER_STRING_TYPE_TAG = ATypeTag.STRING.serialize();

  public static final IFunctionDescriptorFactory FACTORY =
      new IFunctionDescriptorFactory() {
        public IFunctionDescriptor createFunctionDescriptor() {
          return new RegExpDescriptor();
        }
      };

  @Override
  public FunctionIdentifier getIdentifier() {
    return AsterixBuiltinFunctions.REG_EXP;
  }

  @Override
  public ICopyEvaluatorFactory createEvaluatorFactory(final ICopyEvaluatorFactory[] args)
      throws AlgebricksException {

    return new ICopyEvaluatorFactory() {
      private static final long serialVersionUID = 1L;

      @Override
      public ICopyEvaluator createEvaluator(IDataOutputProvider output) throws AlgebricksException {

        final DataOutput dout = output.getDataOutput();

        return new ICopyEvaluator() {

          private boolean first = true;
          private ArrayBackedValueStorage array0 = new ArrayBackedValueStorage();
          private ICopyEvaluator evalString = args[0].createEvaluator(array0);
          private ICopyEvaluator evalPattern = args[1].createEvaluator(array0);
          private ByteArrayAccessibleOutputStream lastPattern =
              new ByteArrayAccessibleOutputStream();
          private UTF8CharSequence carSeq = new UTF8CharSequence();
          private UTF8StringPointable utf8Ptr = new UTF8StringPointable();
          private IBinaryComparator strComp =
              AqlBinaryComparatorFactoryProvider.INSTANCE
                  .getBinaryComparatorFactory(BuiltinType.ASTRING, true)
                  .createBinaryComparator();

          @SuppressWarnings("unchecked")
          private ISerializerDeserializer<AString> stringSerde =
              AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(
                  BuiltinType.ASTRING);

          @SuppressWarnings("unchecked")
          private ISerializerDeserializer<ABoolean> booleanSerde =
              AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(
                  BuiltinType.ABOOLEAN);

          @SuppressWarnings("unchecked")
          private ISerializerDeserializer<ANull> nullSerde =
              AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(
                  BuiltinType.ANULL);

          private Matcher matcher;
          private Pattern pattern;

          @Override
          public void evaluate(IFrameTupleReference tuple) throws AlgebricksException {
            // evaluate the pattern first
            try {
              array0.reset();
              evalPattern.evaluate(tuple);
              if (array0.getByteArray()[0] == SER_NULL_TYPE_TAG) {
                nullSerde.serialize(ANull.NULL, dout);
                return;
              }
              if (array0.getByteArray()[0] != SER_STRING_TYPE_TAG) {
                throw new AlgebricksException(
                    AsterixBuiltinFunctions.REG_EXP.getName()
                        + ": expects type STRING/NULL for the first input argument but got "
                        + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(
                            array0.getByteArray()[0]));
              }
              boolean newPattern = false;
              if (first) {
                first = false;
                newPattern = true;
              } else {
                int c =
                    strComp.compare(
                        array0.getByteArray(),
                        array0.getStartOffset(),
                        array0.getLength(),
                        lastPattern.getByteArray(),
                        0,
                        lastPattern.size());
                if (c != 0) {
                  newPattern = true;
                }
              }
              if (newPattern) {
                lastPattern.reset();
                lastPattern.write(
                    array0.getByteArray(), array0.getStartOffset(), array0.getLength());
                // ! object creation !
                DataInputStream di =
                    new DataInputStream(new ByteArrayInputStream(lastPattern.getByteArray()));
                AString strPattern = (AString) stringSerde.deserialize(di);
                pattern = Pattern.compile(strPattern.getStringValue());
              }
              array0.reset();
              evalString.evaluate(tuple);
              if (array0.getByteArray()[0] == SER_NULL_TYPE_TAG) {
                nullSerde.serialize(ANull.NULL, dout);
                return;
              }
              if (array0.getByteArray()[0] != SER_STRING_TYPE_TAG) {
                throw new AlgebricksException(
                    AsterixBuiltinFunctions.REG_EXP.getName()
                        + ": expects type STRING/NULL for the second input argument but got "
                        + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(
                            array0.getByteArray()[0]));
              }
              utf8Ptr.set(array0.getByteArray(), 1, array0.getLength() - 1);
              carSeq.reset(utf8Ptr);
              if (newPattern) {
                matcher = pattern.matcher(carSeq);
              } else {
                matcher.reset(carSeq);
              }
              ABoolean res = (matcher.find(0)) ? ABoolean.TRUE : ABoolean.FALSE;
              booleanSerde.serialize(res, dout);
            } catch (HyracksDataException e) {
              throw new AlgebricksException(e);
            }
          }
        };
      }
    };
  }
}
  private void parseRecord(ARecordType recType, DataOutput out, Boolean datasetRec)
      throws IOException, AsterixException, AdmLexerException {

    ArrayBackedValueStorage fieldValueBuffer = getTempBuffer();
    ArrayBackedValueStorage fieldNameBuffer = getTempBuffer();
    IARecordBuilder recBuilder = getRecordBuilder();

    BitSet nulls = null;
    if (datasetRec) {
      if (recType != null) {
        nulls = new BitSet(recType.getFieldNames().length);
        recBuilder.reset(recType);
      } else {
        recBuilder.reset(null);
      }
    } else if (recType != null) {
      nulls = new BitSet(recType.getFieldNames().length);
      recBuilder.reset(recType);
    } else {
      recBuilder.reset(null);
    }

    recBuilder.init();
    int token;
    boolean inRecord = true;
    boolean expectingRecordField = false;
    boolean first = true;

    Boolean openRecordField = false;
    int fieldId = 0;
    IAType fieldType = null;
    do {
      token = admLexer.next();
      switch (token) {
        case AdmLexer.TOKEN_END_RECORD:
          {
            if (expectingRecordField) {
              throw new ParseException("Found END_RECORD while expecting a record field.");
            }
            inRecord = false;
            break;
          }
        case AdmLexer.TOKEN_STRING_LITERAL:
          {
            // we've read the name of the field
            // now read the content
            fieldNameBuffer.reset();
            fieldValueBuffer.reset();
            expectingRecordField = false;

            if (recType != null) {
              String fldName =
                  admLexer
                      .getLastTokenImage()
                      .substring(1, admLexer.getLastTokenImage().length() - 1);
              fieldId = recBuilder.getFieldId(fldName);
              if (fieldId < 0 && !recType.isOpen()) {
                throw new ParseException("This record is closed, you can not add extra fields !!");
              } else if (fieldId < 0 && recType.isOpen()) {
                aStringFieldName.setValue(
                    admLexer
                        .getLastTokenImage()
                        .substring(1, admLexer.getLastTokenImage().length() - 1));
                stringSerde.serialize(aStringFieldName, fieldNameBuffer.getDataOutput());
                openRecordField = true;
                fieldType = null;
              } else {
                // a closed field
                nulls.set(fieldId);
                fieldType = recType.getFieldTypes()[fieldId];
                openRecordField = false;
              }
            } else {
              aStringFieldName.setValue(
                  admLexer
                      .getLastTokenImage()
                      .substring(1, admLexer.getLastTokenImage().length() - 1));
              stringSerde.serialize(aStringFieldName, fieldNameBuffer.getDataOutput());
              openRecordField = true;
              fieldType = null;
            }

            token = admLexer.next();
            if (token != AdmLexer.TOKEN_COLON) {
              throw new ParseException(
                  "Unexpected ADM token kind: "
                      + AdmLexer.tokenKindToString(token)
                      + " while expecting \":\".");
            }

            token = admLexer.next();
            this.admFromLexerStream(token, fieldType, fieldValueBuffer.getDataOutput(), false);
            if (openRecordField) {
              if (fieldValueBuffer.getByteArray()[0] != ATypeTag.NULL.serialize()) {
                recBuilder.addField(fieldNameBuffer, fieldValueBuffer);
              }
            } else if (NonTaggedFormatUtil.isOptional(recType)) {
              if (fieldValueBuffer.getByteArray()[0] != ATypeTag.NULL.serialize()) {
                recBuilder.addField(fieldId, fieldValueBuffer);
              }
            } else {
              recBuilder.addField(fieldId, fieldValueBuffer);
            }

            break;
          }
        case AdmLexer.TOKEN_COMMA:
          {
            if (first) {
              throw new ParseException("Found COMMA before any record field.");
            }
            if (expectingRecordField) {
              throw new ParseException("Found COMMA while expecting a record field.");
            }
            expectingRecordField = true;
            break;
          }
        default:
          {
            throw new ParseException(
                "Unexpected ADM token kind: "
                    + AdmLexer.tokenKindToString(token)
                    + " while parsing record fields.");
          }
      }
      first = false;
    } while (inRecord);

    if (recType != null) {
      nullableFieldId = checkNullConstraints(recType, nulls);
      if (nullableFieldId != -1) {
        throw new ParseException(
            "Field: " + recType.getFieldNames()[nullableFieldId] + " can not be null");
      }
    }
    recBuilder.write(out, true);
  }