// validateTypes checks for predicate types present in the schema and validates if the // input value is of the correct type func validateTypes(nquads []rdf.NQuad) error { for i := range nquads { nquad := &nquads[i] if t := schema.TypeOf(nquad.Predicate); t != nil && t.IsScalar() { schemaType := t.(types.Scalar) typeID := types.TypeID(nquad.ObjectType) if typeID == types.BytesID { // Storage type was unspecified in the RDF, so we convert the data to the schema // type. v := types.ValueForType(schemaType.ID()) err := v.UnmarshalText(nquad.ObjectValue) if err != nil { return err } nquad.ObjectValue, err = v.MarshalBinary() if err != nil { return err } nquad.ObjectType = byte(schemaType.ID()) } else if typeID != schemaType.ID() { v := types.ValueForType(typeID) err := v.UnmarshalBinary(nquad.ObjectValue) if err != nil { return err } if _, err := schemaType.Convert(v); err != nil { return err } } } } return nil }
func toRDF(buf *bytes.Buffer, item kv) { pl := item.list for _, p := range pl.Postings { x.Check2(buf.WriteString(item.prefix)) if p.Uid == math.MaxUint64 && !bytes.Equal(p.Value, nil) { // Value posting // Convert to appropriate type typ := stype.ValueForType(stype.TypeID(p.ValType)) x.Check(typ.UnmarshalBinary(p.Value)) str, err := typ.MarshalText() x.Check(err) x.Check2(buf.WriteString(fmt.Sprintf("\"%s\"", str))) if p.ValType == uint32(stype.GeoID) { x.Check2(buf.WriteString(fmt.Sprintf("^^<geo:geojson> "))) } else if p.ValType != uint32(stype.BytesID) { x.Check2(buf.WriteString(fmt.Sprintf("^^<xs:%s> ", typ.Type().Name))) } x.Check2(buf.WriteString(" .\n")) return } x.Check2(buf.WriteString(fmt.Sprintf("<_uid_:%#x> .\n", p.Uid))) } }
// AddMutationWithIndex is AddMutation with support for indexing. func (l *List) AddMutationWithIndex(ctx context.Context, t *task.DirectedEdge, op uint32) error { x.AssertTruef(len(t.Attr) > 0, "[%s] [%d] [%v] %d %d\n", t.Attr, t.Entity, t.Value, t.ValueId, op) var vbytes []byte var vtype byte var verr error doUpdateIndex := pstore != nil && (t.Value != nil) && schema.IsIndexed(t.Attr) if doUpdateIndex { // Check last posting for original value BEFORE any mutation actually happens. vbytes, vtype, verr = l.Value() } hasMutated, err := l.AddMutation(ctx, t, op) if err != nil { return err } if !hasMutated || !doUpdateIndex { return nil } // Exact matches. if verr == nil && len(vbytes) > 0 { delTerm := vbytes delType := vtype p := types.ValueForType(types.TypeID(delType)) if err := p.UnmarshalBinary(delTerm); err != nil { return err } addIndexMutations(ctx, t.Attr, t.Entity, p, true) } if op == Set { p := types.ValueForType(types.TypeID(t.ValueType)) if err := p.UnmarshalBinary(t.Value); err != nil { return err } addIndexMutations(ctx, t.Attr, t.Entity, p, false) } return nil }
// getValue gets the value from the task. func getValue(tv *task.Value) (types.Value, error) { vType := tv.ValType valBytes := tv.Val val := types.ValueForType(types.TypeID(vType)) if val == nil { return nil, x.Errorf("Invalid type: %v", vType) } if err := val.UnmarshalBinary(valBytes); err != nil { return nil, err } return val, nil }
func getValue(attr, data string) (types.Value, error) { // Parse given value and get token. There should be only one token. t := schema.TypeOf(attr) if t == nil || !t.IsScalar() { return nil, x.Errorf("Attribute %s is not valid scalar type", attr) } schemaType := t.(types.Scalar) v := types.ValueForType(schemaType.ID()) err := v.UnmarshalText([]byte(data)) if err != nil { return nil, err } return v, nil }
// getPostingValue looks up key, gets the value, converts it. If any error is // encountered, we return nil. This is used in some filtering where we do not // want to waste time creating errors. func getPostingValue(key []byte, scalarType types.Scalar) *types.Value { pl, decr := posting.GetOrCreate(key) defer decr() valBytes, vType, err := pl.Value() if bytes.Equal(valBytes, nil) { return nil } val := types.ValueForType(types.TypeID(vType)) if val == nil { return nil } if err := val.UnmarshalBinary(valBytes); err != nil { return nil } // Convert to schema type. sv, err := scalarType.Convert(val) if err != nil { return nil } return &sv }
// fetchValue gets the value for a given UID. func fetchValue(uid uint64, attr string, scalar types.Scalar) (types.Value, error) { pl, decr := posting.GetOrCreate(x.DataKey(attr, uid)) defer decr() valBytes, vType, err := pl.Value() if err != nil { return nil, err } val := types.ValueForType(types.TypeID(vType)) if val == nil { return nil, x.Errorf("Invalid type: %v", vType) } err = val.UnmarshalBinary(valBytes) if err != nil { return nil, err } schemaVal, err := scalar.Convert(val) if err != nil { return nil, err } return schemaVal, nil }
// Parse parses a mutation string and returns the NQuad representation for it. func Parse(line string) (rnq NQuad, rerr error) { l := &lex.Lexer{} l.Init(line) go run(l) var oval string var vend bool // We read items from the l.Items channel to which the lexer sends items. for item := range l.Items { switch item.Typ { case itemSubject: rnq.Subject = stripBracketsAndTrim(item.Val) case itemPredicate: rnq.Predicate = stripBracketsAndTrim(item.Val) case itemObject: rnq.ObjectId = stripBracketsAndTrim(item.Val) case itemLiteral: oval = item.Val case itemLanguage: rnq.Predicate += "." + item.Val case itemObjectType: if len(oval) == 0 { log.Fatalf( "itemObject should be emitted before itemObjectType. Input: [%s]", line) } val := stripBracketsAndTrim(item.Val) if strings.Trim(val, " ") == "*" { return rnq, fmt.Errorf("itemObject can't be *") } if t, ok := typeMap[val]; ok { p := types.ValueForType(t) err := p.UnmarshalText([]byte(oval)) if err != nil { return rnq, err } rnq.ObjectValue, err = p.MarshalBinary() if err != nil { return rnq, err } rnq.ObjectType = byte(t) oval = "" } else { oval += "@@" + val } case lex.ItemError: return rnq, fmt.Errorf(item.Val) case itemValidEnd: vend = true case itemLabel: rnq.Label = stripBracketsAndTrim(item.Val) } } if !vend { return rnq, fmt.Errorf("Invalid end of input. Input: [%s]", line) } if len(oval) > 0 { rnq.ObjectValue = []byte(oval) // If no type is specified, we default to string. rnq.ObjectType = 0 } if len(rnq.Subject) == 0 || len(rnq.Predicate) == 0 { return rnq, fmt.Errorf("Empty required fields in NQuad. Input: [%s]", line) } if len(rnq.ObjectId) == 0 && rnq.ObjectValue == nil { return rnq, fmt.Errorf("No Object in NQuad. Input: [%s]", line) } if !sane(rnq.Subject) || !sane(rnq.Predicate) || !sane(rnq.ObjectId) || !sane(rnq.Label) { return rnq, fmt.Errorf("NQuad failed sanity check:%+v", rnq) } return rnq, nil }