@@ -334,13 +334,12 @@ func (f *UASTXPath) Eval(ctx *sql.Context, row sql.Row) (out interface{}, err er
334
334
return nil , err
335
335
}
336
336
337
- for _ , n := range ns {
338
- data , err := n .Marshal ()
339
- if err != nil {
340
- return nil , err
341
- }
342
- result = append (result , data )
337
+ m , err := marshalNodes (ns )
338
+ if err != nil {
339
+ return nil , err
343
340
}
341
+
342
+ result = append (result , m ... )
344
343
}
345
344
346
345
return result , nil
@@ -359,12 +358,29 @@ func nodesFromBlobArray(data interface{}) ([]*uast.Node, error) {
359
358
if err := node .Unmarshal (n .([]byte )); err != nil {
360
359
return nil , err
361
360
}
361
+
362
362
nodes [i ] = node
363
363
}
364
364
365
365
return nodes , nil
366
366
}
367
367
368
+ func marshalNodes (nodes []* uast.Node ) ([]interface {}, error ) {
369
+ m := make ([]interface {}, 0 , len (nodes ))
370
+ for _ , n := range nodes {
371
+ if n != nil {
372
+ data , err := n .Marshal ()
373
+ if err != nil {
374
+ return nil , err
375
+ }
376
+
377
+ m = append (m , data )
378
+ }
379
+ }
380
+
381
+ return m , nil
382
+ }
383
+
368
384
func (f UASTXPath ) String () string {
369
385
return fmt .Sprintf ("uast_xpath(%s, %s)" , f .Left , f .Right )
370
386
}
@@ -459,18 +475,7 @@ func getUAST(
459
475
}
460
476
}
461
477
462
- var result = make ([]interface {}, 0 , len (nodes ))
463
- for _ , n := range nodes {
464
- if n != nil {
465
- node , err := n .Marshal ()
466
- if err != nil {
467
- return nil , err
468
- }
469
- result = append (result , node )
470
- }
471
- }
472
-
473
- return result , nil
478
+ return marshalNodes (nodes )
474
479
}
475
480
476
481
// UASTExtract extracts keys from an UAST.
@@ -586,3 +591,73 @@ func (u *UASTExtract) TransformUp(f sql.TransformExprFunc) (sql.Expression, erro
586
591
587
592
return f (NewUASTExtract (left , rigth ))
588
593
}
594
+
595
+ // UASTChildren returns children from UAST nodes.
596
+ type UASTChildren struct {
597
+ expression.UnaryExpression
598
+ }
599
+
600
+ // NewUASTChildren creates a new UASTExtract UDF.
601
+ func NewUASTChildren (uast sql.Expression ) sql.Expression {
602
+ return & UASTChildren {expression.UnaryExpression {Child : uast }}
603
+ }
604
+
605
+ // String implements the fmt.Stringer interface.
606
+ func (u * UASTChildren ) String () string {
607
+ return fmt .Sprintf ("uast_children(%s)" , u .Child )
608
+ }
609
+
610
+ // Type implements the sql.Expression interface.
611
+ func (u * UASTChildren ) Type () sql.Type {
612
+ return sql .Array (sql .Blob )
613
+ }
614
+
615
+ // TransformUp implements the sql.Expression interface.
616
+ func (u * UASTChildren ) TransformUp (f sql.TransformExprFunc ) (sql.Expression , error ) {
617
+ child , err := u .Child .TransformUp (f )
618
+ if err != nil {
619
+ return nil , err
620
+ }
621
+
622
+ return f (NewUASTChildren (child ))
623
+ }
624
+
625
+ // Eval implements the sql.Expression interface.
626
+ func (u * UASTChildren ) Eval (ctx * sql.Context , row sql.Row ) (out interface {}, err error ) {
627
+ defer func () {
628
+ if r := recover (); r != nil {
629
+ err = fmt .Errorf ("uast: unknown error: %s" , r )
630
+ }
631
+ }()
632
+
633
+ span , ctx := ctx .Span ("gitbase.UASTChildren" )
634
+ defer span .Finish ()
635
+
636
+ child , err := u .Child .Eval (ctx , row )
637
+ if err != nil {
638
+ return nil , err
639
+ }
640
+
641
+ if child == nil {
642
+ return nil , nil
643
+ }
644
+
645
+ nodes , err := nodesFromBlobArray (child )
646
+ if err != nil {
647
+ return nil , err
648
+ }
649
+
650
+ children := flattenChildren (nodes )
651
+ return marshalNodes (children )
652
+ }
653
+
654
+ func flattenChildren (nodes []* uast.Node ) []* uast.Node {
655
+ children := []* uast.Node {}
656
+ for _ , n := range nodes {
657
+ if len (n .Children ) > 0 {
658
+ children = append (children , n .Children ... )
659
+ }
660
+ }
661
+
662
+ return children
663
+ }
0 commit comments