func toQuadValue(o interface{}) (quad.Value, bool) { var qv quad.Value switch v := o.(type) { case quadValue: qv = v.v case quad.Value: qv = v case string: qv = quad.Raw(v) case bool: qv = quad.Bool(v) case int: qv = quad.Int(v) case int64: qv = quad.Int(v) case float64: if float64(int(v)) == v { qv = quad.Int(int64(v)) } else { qv = quad.Float(v) } case time.Time: qv = quad.Time(v) default: return nil, false } return qv, true }
func toQuadValue(v value) quad.Value { if v == nil { return nil } switch d := v.(type) { case string: return quad.Raw(d) // compatibility case int64: return quad.Int(d) case float64: return quad.Float(d) case bool: return quad.Bool(d) case time.Time: return quad.Time(d) case bson.M: // TODO(dennwc): use raw document instead? so, ok := d["val"] if !ok { glog.Errorf("Error: Empty value in map: %v", v) return nil } s := so.(string) if len(d) == 1 { return quad.String(s) } if o, ok := d["iri"]; ok && o.(bool) { return quad.IRI(s) } else if o, ok := d["bnode"]; ok && o.(bool) { return quad.BNode(s) } else if o, ok := d["lang"]; ok && o.(string) != "" { return quad.LangString{ Value: quad.String(s), Lang: o.(string), } } else if o, ok := d["type"]; ok && o.(string) != "" { return quad.TypedString{ Value: quad.String(s), Type: quad.IRI(o.(string)), } } return quad.String(s) case []byte: var p proto.Value if err := p.Unmarshal(d); err != nil { glog.Errorf("Error: Couldn't decode value: %v", err) return nil } return p.ToNative() default: panic(fmt.Errorf("unsupported type: %T", v)) } }
func TestCompareTypedValues(t testing.TB, gen DatabaseFunc, conf *Config) { qs, opts, closer := gen(t) defer closer() w := MakeWriter(t, qs, opts) t1 := tzero t2 := t1.Add(time.Hour) t3 := t2.Add(time.Hour * 48) t4 := t1.Add(time.Hour * 24 * 365) err := w.AddQuadSet([]quad.Quad{ {quad.BNode("alice"), quad.BNode("bob"), quad.BNode("charlie"), quad.BNode("dani")}, {quad.IRI("alice"), quad.IRI("bob"), quad.IRI("charlie"), quad.IRI("dani")}, {quad.String("alice"), quad.String("bob"), quad.String("charlie"), quad.String("dani")}, {quad.Int(100), quad.Int(112), quad.Int(110), quad.Int(20)}, {quad.Time(t1), quad.Time(t2), quad.Time(t3), quad.Time(t4)}, }) require.Nil(t, err) for _, c := range casesCompare { it := iterator.NewComparison(qs.NodesAllIterator(), c.op, c.val, qs) ExpectIteratedValues(t, qs, it, c.expect) } for _, c := range casesCompare { it := iterator.NewComparison(qs.NodesAllIterator(), c.op, c.val, qs) nit, ok := qs.OptimizeIterator(it) require.Equal(t, conf.OptimizesComparison, ok) if conf.OptimizesComparison { require.NotEqual(t, it, nit) } else { require.Equal(t, it, nit) } ExpectIteratedValues(t, qs, nit, c.expect) } }
// ToNative converts protobuf Value to quad.Value. func (m *Value) ToNative() (qv quad.Value) { if m == nil { return nil } switch v := m.Value.(type) { case *Value_Raw: return quad.Raw(v.Raw) case *Value_Str: return quad.String(v.Str) case *Value_Iri: return quad.IRI(v.Iri) case *Value_Bnode: return quad.BNode(v.Bnode) case *Value_TypedStr: return quad.TypedString{ Value: quad.String(v.TypedStr.Value), Type: quad.IRI(v.TypedStr.Type), } case *Value_LangStr: return quad.LangString{ Value: quad.String(v.LangStr.Value), Lang: v.LangStr.Lang, } case *Value_Int: return quad.Int(v.Int) case *Value_Float_: return quad.Float(v.Float_) case *Value_Boolean: return quad.Bool(v.Boolean) case *Value_Time: var t time.Time if v.Time == nil { t = time.Unix(0, 0).UTC() } else { t = time.Unix(v.Time.Seconds, int64(v.Time.Nanos)).UTC() } return quad.Time(t) default: panic(fmt.Errorf("unsupported type: %T", m.Value)) } }
func (qs *QuadStore) NameOf(v graph.Value) quad.Value { if v == nil { glog.V(2).Info("NameOf was nil") return nil } hash := v.(NodeHash) if !hash.Valid() { glog.V(2).Info("NameOf was nil") return nil } if val, ok := qs.ids.Get(hash.String()); ok { return val.(quad.Value) } query := `SELECT value, value_string, datatype, language, iri, bnode, value_int, value_bool, value_float, value_time FROM nodes WHERE hash = $1 LIMIT 1;` c := qs.db.QueryRow(query, hash.toSQL()) var ( data []byte str sql.NullString typ sql.NullString lang sql.NullString iri sql.NullBool bnode sql.NullBool vint sql.NullInt64 vbool sql.NullBool vfloat sql.NullFloat64 vtime pq.NullTime ) if err := c.Scan( &data, &str, &typ, &lang, &iri, &bnode, &vint, &vbool, &vfloat, &vtime, ); err != nil { glog.Errorf("Couldn't execute value lookup: %v", err) return nil } var val quad.Value if str.Valid { if iri.Bool { val = quad.IRI(str.String) } else if bnode.Bool { val = quad.BNode(str.String) } else if lang.Valid { val = quad.LangString{ Value: quad.String(unescapeNullByte(str.String)), Lang: lang.String, } } else if typ.Valid { val = quad.TypedString{ Value: quad.String(unescapeNullByte(str.String)), Type: quad.IRI(typ.String), } } else { val = quad.String(unescapeNullByte(str.String)) } } else if vint.Valid { val = quad.Int(vint.Int64) } else if vbool.Valid { val = quad.Bool(vbool.Bool) } else if vfloat.Valid { val = quad.Float(vfloat.Float64) } else if vtime.Valid { val = quad.Time(vtime.Time) } else { qv, err := proto.UnmarshalValue(data) if err != nil { glog.Errorf("Couldn't unmarshal value: %v", err) return nil } val = qv } if val != nil { qs.ids.Put(hash.String(), val) } return val }
Label: nil, }, err: nil, }, { message: "parse triple with IRIREF schema on literal object and dateTime", input: `<http://example.org/bob#me> <http://schema.org/birthDate> "1990-07-04T17:25:41Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .`, expect: quad.Quad{ Subject: quad.IRI("http://example.org/bob#me"), Predicate: quad.IRI("http://schema.org/birthDate"), Object: func() quad.Time { t, err := time.Parse(time.RFC3339, "1990-07-04T17:25:41Z") if err != nil { panic(err) } return quad.Time(t) }(), Label: nil, }, err: nil, }, { message: "parse commented IRIREF in triple", input: `<http://example.org/bob#me> <http://xmlns.com/foaf/0.1/topic_interest> <http://www.wikidata.org/entity/Q12418> .`, expect: quad.Quad{ Subject: quad.IRI("http://example.org/bob#me"), Predicate: quad.IRI("http://xmlns.com/foaf/0.1/topic_interest"), Object: quad.IRI("http://www.wikidata.org/entity/Q12418"), Label: nil, }, err: nil,
func TestLoadTypedQuads(t testing.TB, gen DatabaseFunc, conf *Config) { qs, opts, closer := gen(t) defer closer() w := MakeWriter(t, qs, opts) values := []quad.Value{ quad.BNode("A"), quad.IRI("name"), quad.String("B"), quad.IRI("graph"), quad.IRI("B"), quad.Raw("<type>"), quad.TypedString{Value: "10", Type: "int"}, quad.LangString{Value: "value", Lang: "en"}, quad.Int(-123456789), quad.Float(-12345e-6), quad.Bool(true), quad.Time(time.Now()), } err := w.AddQuadSet([]quad.Quad{ {values[0], values[1], values[2], values[3]}, {values[4], values[5], values[6], nil}, {values[4], values[5], values[7], nil}, {values[0], values[1], values[8], nil}, {values[0], values[1], values[9], nil}, {values[0], values[1], values[10], nil}, {values[0], values[1], values[11], nil}, }) require.Nil(t, err) for _, pq := range values { got := qs.NameOf(qs.ValueOf(pq)) if !conf.UnTyped { if pt, ok := pq.(quad.Time); ok { var trim int64 if conf.TimeInMcs { trim = 1000 } else if conf.TimeInMs { trim = 1000000 } if trim > 0 { tm := time.Time(pt) seconds := tm.Unix() nanos := int64(tm.Sub(time.Unix(seconds, 0))) if conf.TimeRound { nanos = (nanos/trim + ((nanos/(trim/10))%10)/5) * trim } else { nanos = (nanos / trim) * trim } pq = quad.Time(time.Unix(seconds, nanos).UTC()) } } if eq, ok := pq.(quad.Equaler); ok { assert.True(t, eq.Equal(got), "Failed to roundtrip %q (%T), got %q (%T)", pq, pq, got, got) } else { assert.Equal(t, pq, got, "Failed to roundtrip %q (%T)", pq, pq) if !conf.NoHashes { assert.Equal(t, pq, qs.NameOf(qs.ValueOf(quad.Raw(pq.String()))), "Failed to exchange raw value %q (%T)", pq, pq) } } } else { assert.Equal(t, quad.StringOf(pq), quad.StringOf(got), "Failed to roundtrip raw %q (%T)", pq, pq) } } require.Equal(t, int64(7), qs.Size(), "Unexpected quadstore size") }
quad.IRI("alice"), quad.IRI("bob"), }}, {lte, quad.IRI("bob"), []quad.Value{ quad.IRI("alice"), quad.IRI("bob"), }}, {gte, quad.Int(111), []quad.Value{ quad.Int(112), }}, {gte, quad.Int(110), []quad.Value{ quad.Int(110), quad.Int(112), }}, {lt, quad.Int(20), nil}, {lte, quad.Int(20), []quad.Value{ quad.Int(20), }}, {lte, quad.Time(tzero.Add(time.Hour)), []quad.Value{ quad.Time(tzero), quad.Time(tzero.Add(time.Hour)), }}, {gt, quad.Time(tzero.Add(time.Hour)), []quad.Value{ quad.Time(tzero.Add(time.Hour * 49)), quad.Time(tzero.Add(time.Hour * 24 * 365)), }}, } func TestCompareTypedValues(t testing.TB, gen DatabaseFunc, conf *Config) { qs, opts, closer := gen(t) defer closer() w := MakeWriter(t, qs, opts) t1 := tzero t2 := t1.Add(time.Hour)