Skip to content

Commit 9bb4c00

Browse files
haoxinsNicole00
andauthored
Support scan Nebula subgraph results (vertex and edge) and slice of struct ptr (#346)
* Support scan Nebula vertex and edge * fix: adjust the slice length debug * support struct ptr in the slice * Add tests * Add more props * Add supports for slice of struct ptr * check the empty and null value * no use SetZero --------- Co-authored-by: Anqi <[email protected]>
1 parent e6ae114 commit 9bb4c00

File tree

2 files changed

+422
-26
lines changed

2 files changed

+422
-26
lines changed

result_set.go

Lines changed: 148 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -335,13 +335,19 @@ func (res ResultSet) Scan(v interface{}) error {
335335
}
336336

337337
// Scan scans the rows into the given value.
338-
func (res ResultSet) scanRow(row *nebula.Row, colNames []string, t reflect.Type) (reflect.Value, error) {
338+
func (res ResultSet) scanRow(row *nebula.Row, colNames []string, rowType reflect.Type) (reflect.Value, error) {
339339
rowVals := row.GetValues()
340340

341-
val := reflect.New(t).Elem()
341+
var result reflect.Value
342+
if rowType.Kind() == reflect.Ptr {
343+
result = reflect.New(rowType.Elem())
344+
} else {
345+
result = reflect.New(rowType).Elem()
346+
}
347+
structVal := reflect.Indirect(result)
342348

343-
for fIdx := 0; fIdx < t.NumField(); fIdx++ {
344-
f := t.Field(fIdx)
349+
for fIdx := 0; fIdx < structVal.Type().NumField(); fIdx++ {
350+
f := structVal.Type().Field(fIdx)
345351
tag := f.Tag.Get("nebula")
346352

347353
if tag == "" {
@@ -356,31 +362,147 @@ func (res ResultSet) scanRow(row *nebula.Row, colNames []string, t reflect.Type)
356362

357363
rowVal := rowVals[cIdx]
358364

359-
switch f.Type.Kind() {
360-
case reflect.Bool:
361-
val.Field(fIdx).SetBool(rowVal.GetBVal())
362-
case reflect.Int:
363-
val.Field(fIdx).SetInt(rowVal.GetIVal())
364-
case reflect.Int8:
365-
val.Field(fIdx).SetInt(rowVal.GetIVal())
366-
case reflect.Int16:
367-
val.Field(fIdx).SetInt(rowVal.GetIVal())
368-
case reflect.Int32:
369-
val.Field(fIdx).SetInt(rowVal.GetIVal())
370-
case reflect.Int64:
371-
val.Field(fIdx).SetInt(rowVal.GetIVal())
372-
case reflect.Float32:
373-
val.Field(fIdx).SetFloat(rowVal.GetFVal())
374-
case reflect.Float64:
375-
val.Field(fIdx).SetFloat(rowVal.GetFVal())
376-
case reflect.String:
377-
val.Field(fIdx).SetString(string(rowVal.GetSVal()))
378-
default:
379-
return val, errors.New("scan: not support type")
365+
if f.Type.Kind() == reflect.Slice {
366+
list := rowVal.GetLVal()
367+
err := scanListCol(list.Values, structVal.Field(fIdx), f.Type)
368+
if err != nil {
369+
return result, err
370+
}
371+
} else {
372+
err := scanPrimitiveCol(rowVal, structVal.Field(fIdx), f.Type.Kind())
373+
if err != nil {
374+
return result, err
375+
}
376+
}
377+
}
378+
379+
return result, nil
380+
}
381+
382+
func scanListCol(vals []*nebula.Value, listVal reflect.Value, sliceType reflect.Type) error {
383+
switch sliceType.Elem().Kind() {
384+
case reflect.Struct:
385+
var listCol = reflect.MakeSlice(sliceType, 0, len(vals))
386+
for _, val := range vals {
387+
ele := reflect.New(sliceType.Elem()).Elem()
388+
err := scanStructField(val, ele, sliceType.Elem())
389+
if err != nil {
390+
return err
391+
}
392+
listCol = reflect.Append(listCol, ele)
393+
}
394+
listVal.Set(listCol)
395+
case reflect.Ptr:
396+
var listCol = reflect.MakeSlice(sliceType, 0, len(vals))
397+
for _, val := range vals {
398+
ele := reflect.New(sliceType.Elem().Elem())
399+
err := scanStructField(val, reflect.Indirect(ele), sliceType.Elem().Elem())
400+
if err != nil {
401+
return err
402+
}
403+
listCol = reflect.Append(listCol, ele)
380404
}
405+
listVal.Set(listCol)
406+
default:
407+
return errors.New("scan: not support list type")
381408
}
382409

383-
return val, nil
410+
return nil
411+
}
412+
413+
func scanStructField(val *nebula.Value, eleVal reflect.Value, eleType reflect.Type) error {
414+
vertex := val.GetVVal()
415+
if vertex != nil {
416+
tags := vertex.GetTags()
417+
vid := vertex.GetVid()
418+
419+
if len(tags) != 0 {
420+
tag := tags[0]
421+
422+
props := tag.GetProps()
423+
props["_vid"] = vid
424+
tagName := tag.GetName()
425+
props["_tag_name"] = &nebula.Value{SVal: tagName}
426+
427+
err := scanValFromProps(props, eleVal, eleType)
428+
if err != nil {
429+
return err
430+
}
431+
return nil
432+
}
433+
// no tags, continue
434+
}
435+
436+
edge := val.GetEVal()
437+
if edge != nil {
438+
props := edge.GetProps()
439+
440+
src := edge.GetSrc()
441+
dst := edge.GetDst()
442+
name := edge.GetName()
443+
props["_src"] = src
444+
props["_dst"] = dst
445+
props["_name"] = &nebula.Value{SVal: name}
446+
447+
err := scanValFromProps(props, eleVal, eleType)
448+
if err != nil {
449+
return err
450+
}
451+
return nil
452+
}
453+
454+
return nil
455+
}
456+
457+
func scanValFromProps(props map[string]*nebula.Value, val reflect.Value, tpe reflect.Type) error {
458+
for fIdx := 0; fIdx < tpe.NumField(); fIdx++ {
459+
f := tpe.Field(fIdx)
460+
n := f.Tag.Get("nebula")
461+
v, ok := props[n]
462+
if !ok {
463+
continue
464+
}
465+
err := scanPrimitiveCol(v, val.Field(fIdx), f.Type.Kind())
466+
if err != nil {
467+
return err
468+
}
469+
}
470+
471+
return nil
472+
}
473+
474+
func scanPrimitiveCol(rowVal *nebula.Value, val reflect.Value, kind reflect.Kind) error {
475+
w := ValueWrapper{value: rowVal}
476+
if w.IsNull() || w.IsEmpty() {
477+
// SetZero is introduced in go 1.20
478+
// val.SetZero()
479+
return nil
480+
}
481+
482+
switch kind {
483+
case reflect.Bool:
484+
val.SetBool(rowVal.GetBVal())
485+
case reflect.Int:
486+
val.SetInt(rowVal.GetIVal())
487+
case reflect.Int8:
488+
val.SetInt(rowVal.GetIVal())
489+
case reflect.Int16:
490+
val.SetInt(rowVal.GetIVal())
491+
case reflect.Int32:
492+
val.SetInt(rowVal.GetIVal())
493+
case reflect.Int64:
494+
val.SetInt(rowVal.GetIVal())
495+
case reflect.Float32:
496+
val.SetFloat(rowVal.GetFVal())
497+
case reflect.Float64:
498+
val.SetFloat(rowVal.GetFVal())
499+
case reflect.String:
500+
val.SetString(string(rowVal.GetSVal()))
501+
default:
502+
return errors.New("scan: not support primitive type")
503+
}
504+
505+
return nil
384506
}
385507

386508
// Returns the number of total rows

0 commit comments

Comments
 (0)