func getIdentValueFromOuterQuery(ctx context.Context, name string) (interface{}, error) { s := getRowStack(ctx) if s == nil { return nil, errors.Errorf("unknown field %s", name) } // The top is current RowStack, use its last. n := len(s.items) - 2 var ( v interface{} err error ) for ; n >= 0; n-- { t := s.items[n] // first try to get from outer table reference. if t.FromData != nil { v, err = GetIdentValue(name, t.FromDataFields, t.FromData) if err == nil { // tell current subquery using outer query subquery.SetOuterQueryUsed(ctx) return v, nil } } // then try to get from outer select list. if t.OutData != nil { v, err = GetIdentValue(name, t.OutDataFields, t.OutData) if err == nil { // tell current subquery using outer query subquery.SetOuterQueryUsed(ctx) return v, nil } } } return nil, errors.Errorf("unknown field %s", name) }
func (s *testSubQuerySuite) TestSubQuery(c *C) { e := &subquery.SubQuery{ Val: 1, } ctx := mock.NewContext() c.Assert(e.IsStatic(), IsFalse) str := e.String() c.Assert(str, Equals, "") ec := e.Clone() v, err := ec.Eval(ctx, nil) c.Assert(err, IsNil) c.Assert(v, Equals, 1) e2, ok := ec.(*subquery.SubQuery) c.Assert(ok, IsTrue) e2 = newMockSubQuery([][]interface{}{{1}}, []string{"id"}) vv, err := e2.Eval(ctx, nil) c.Assert(err, IsNil) c.Assert(vv, Equals, 1) e2.SetValue(nil) vv, err = e2.Eval(ctx, nil) c.Assert(err, IsNil) c.Assert(vv, Equals, 1) e2 = newMockSubQuery([][]interface{}{{1, 2}}, []string{"id", "name"}) vv, err = e2.Eval(ctx, nil) c.Assert(err, IsNil) c.Assert(vv, DeepEquals, []interface{}{1, 2}) e2 = newMockSubQuery([][]interface{}{{1}, {2}}, []string{"id"}) _, err = e2.Eval(ctx, nil) c.Assert(err, NotNil) str = e2.String() c.Assert(len(str), Greater, 0) e2 = newMockSubQuery([][]interface{}{{1, 2}}, []string{"id", "name"}) count, err := e2.ColumnCount(nil) c.Assert(err, IsNil) c.Assert(count, Equals, 2) count, err = e2.ColumnCount(nil) c.Assert(err, IsNil) c.Assert(count, Equals, 2) e3 := newMockSubQuery([][]interface{}{{1, 2}}, []string{"id", "name"}) e2.Push(ctx) e3.Push(ctx) c.Assert(e2.UseOuter, IsFalse) c.Assert(e3.UseOuter, IsFalse) subquery.SetOuterQueryUsed(ctx) c.Assert(e2.UseOuterQuery, IsTrue) c.Assert(e3.UseOuterQuery, IsTrue) err = e2.Pop(ctx) c.Assert(err, NotNil) err = e3.Pop(ctx) subquery.SetOuterQueryUsed(ctx) err = e2.Pop(ctx) c.Assert(err, IsNil) err = e2.Pop(ctx) c.Assert(err, NotNil) subquery.SetOuterQueryUsed(ctx) c.Assert(len(subquery.SubQueryStackKey.String()), Greater, 0) }