private int checkNullConstraints(ARecordType recType, BitSet nulls) { boolean isNull = false; for (int i = 0; i < recType.getFieldTypes().length; i++) { if (nulls.get(i) == false) { IAType type = recType.getFieldTypes()[i]; if (type.getTypeTag() != ATypeTag.NULL && type.getTypeTag() != ATypeTag.UNION) { return i; } if (type.getTypeTag() == ATypeTag.UNION) { // union List<IAType> unionList = ((AUnionType) type).getUnionList(); for (int j = 0; j < unionList.size(); j++) { if (unionList.get(j).getTypeTag() == ATypeTag.NULL) { isNull = true; break; } } if (!isNull) { return i; } } } } return -1; }
@Override public IAType computeType( ILogicalExpression expression, IVariableTypeEnvironment env, IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException { AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) expression; Object obj; try { obj = env.getType(f.getArguments().get(0).getValue()); } catch (AlgebricksException e) { throw new AlgebricksException(e); } if (obj == null) { return null; } IAType type0 = (IAType) obj; ARecordType t0 = NonTaggedFieldAccessByNameResultType.getRecordTypeFromType(type0, expression); if (t0 == null) { return BuiltinType.ANY; } ILogicalExpression arg1 = f.getArguments().get(1).getValue(); if (arg1.getExpressionTag() != LogicalExpressionTag.CONSTANT) { return BuiltinType.ANY; } ConstantExpression ce = (ConstantExpression) arg1; if (!(ce.getValue() instanceof AsterixConstantValue)) { throw new AlgebricksException( "Typing error: expecting an integer, found " + ce + " instead."); } IAObject v = ((AsterixConstantValue) ce.getValue()).getObject(); if (v.getType().getTypeTag() != ATypeTag.INT32) { throw new AlgebricksException("Typing error: expecting an INT32, found " + ce + " instead."); } int pos = ((AInt32) v).getIntegerValue(); return t0.getFieldTypes()[pos]; }
@Override public JRecord access( ARecordVisitablePointable pointable, IObjectPool<IJObject, IAType> objectPool, ARecordType recordType, JObjectPointableVisitor pointableVisitor) throws HyracksDataException { try { jRecord.reset(); } catch (AlgebricksException e) { throw new HyracksDataException(e); } ARecordVisitablePointable recordPointable = (ARecordVisitablePointable) pointable; List<IVisitablePointable> fieldPointables = recordPointable.getFieldValues(); List<IVisitablePointable> fieldTypeTags = recordPointable.getFieldTypeTags(); List<IVisitablePointable> fieldNames = recordPointable.getFieldNames(); int index = 0; boolean closedPart = true; try { IJObject fieldObject = null; for (IVisitablePointable fieldPointable : fieldPointables) { closedPart = index < recordType.getFieldTypes().length; IVisitablePointable tt = fieldTypeTags.get(index); IAType fieldType = closedPart ? recordType.getFieldTypes()[index] : null; ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize( tt.getByteArray()[tt.getStartOffset()]); IVisitablePointable fieldName = fieldNames.get(index); typeInfo.reset(fieldType, typeTag); switch (typeTag) { case RECORD: fieldObject = pointableVisitor.visit((ARecordVisitablePointable) fieldPointable, typeInfo); break; case ORDEREDLIST: case UNORDEREDLIST: if (fieldPointable instanceof AFlatValuePointable) { // value is null fieldObject = null; } else { fieldObject = pointableVisitor.visit((AListVisitablePointable) fieldPointable, typeInfo); } break; case ANY: break; default: fieldObject = pointableVisitor.visit((AFlatValuePointable) fieldPointable, typeInfo); } if (closedPart) { jObjects[index] = fieldObject; } else { byte[] b = fieldName.getByteArray(); int s = fieldName.getStartOffset(); int l = fieldName.getLength(); String v = AStringSerializerDeserializer.INSTANCE .deserialize(new DataInputStream(new ByteArrayInputStream(b, s + 1, l - 1))) .getStringValue(); openFields.put(v, fieldObject); } index++; fieldObject = null; } } catch (Exception e) { e.printStackTrace(); throw new HyracksDataException(e); } return jRecord; }
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); }