Example #1
0
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)
		}
	}
}
Example #2
0
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)
		}
	}
}