func (p *UnionPlan) fetchSrc(ctx context.Context, i int, t memkv.Temp) error { src := p.Srcs[i+1] distinct := p.Distincts[i] // Use the ResultFields of the first select statement as the final ResultFields rfs := p.Srcs[0].GetFields() if len(src.GetFields()) != len(rfs) { return errors.New("The used SELECT statements have a different number of columns") } for { row, err := src.Next(ctx) if row == nil || err != nil { return errors.Trace(err) } srcRfs := src.GetFields() for i := range row.Data { // The column value should be casted as the same type of the first select statement in corresponding position srcRf := srcRfs[i] rf := rfs[i] /* * The lengths of the columns in the UNION result take into account the values retrieved by all of the SELECT statements * SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10); * +---------------+ * | REPEAT('a',1) | * +---------------+ * | a | * | bbbbbbbbbb | * +---------------+ */ if srcRf.Flen > rf.Col.Flen { rf.Col.Flen = srcRf.Col.Flen } row.Data[i], err = types.Convert(row.Data[i], &rf.Col.FieldType) if err != nil { return errors.Trace(err) } } if distinct { // distinct union, check duplicate v, getErr := t.Get(row.Data) if getErr != nil { return errors.Trace(getErr) } if len(v) > 0 { // Find duplicate, ignore it continue } } p.rows = append(p.rows, row) if err := t.Set(row.Data, []interface{}{true}); err != nil { return errors.Trace(err) } } }
func (p *UnionPlan) fetchSrc(ctx context.Context, i int, t memkv.Temp) error { src := p.Srcs[i+1] distinct := p.Distincts[i] rfs := p.GetFields() if len(src.GetFields()) != len(rfs) { return errors.New("The used SELECT statements have a different number of columns") } for { row, err := src.Next(ctx) if row == nil || err != nil { return errors.Trace(err) } srcRfs := src.GetFields() for i := range row.Data { // The column value should be casted as the same type of the first select statement in corresponding position srcRf := srcRfs[i] rf := rfs[i] /* * The lengths of the columns in the UNION result take into account the values retrieved by all of the SELECT statements * SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10); * +---------------+ * | REPEAT('a',1) | * +---------------+ * | a | * | bbbbbbbbbb | * +---------------+ */ if srcRf.Flen > rf.Col.Flen { rf.Col.Flen = srcRf.Col.Flen } if rf.Col.FieldType.Tp > 0 { row.Data[i], err = types.Convert(row.Data[i], &rf.Col.FieldType) } else { // First select result doesn't contain enough type information, e,g, select null union select 1. // We cannot get the proper data type for select null. // Now we just use the first correct return data types with following select. // TODO: Try to merge all data types for all select like select null union select 1 union select "abc" if tp := srcRf.Col.FieldType.Tp; tp > 0 { rf.Col.FieldType.Tp = tp } } if err != nil { return errors.Trace(err) } } if distinct { // distinct union, check duplicate v, getErr := t.Get(row.Data) if getErr != nil { return errors.Trace(getErr) } if len(v) > 0 { // Find duplicate, ignore it continue } } p.rows = append(p.rows, row) if err := t.Set(row.Data, []interface{}{true}); err != nil { return errors.Trace(err) } } }