func encodeStartConstraintDescending( spans []span, c *parser.ComparisonExpr) { switch c.Operator { case parser.Is: // An IS NULL expressions allows us to constrain the start of the range // to begin at NULL. if c.Right != parser.DNull { panic(fmt.Sprintf("expected NULL operand for IS operator, found %v", c.Right)) } for i := range spans { spans[i].start = encoding.EncodeNullDescending(spans[i].start) } case parser.NE: panic("'!=' operators should have been transformed to 'IS NOT NULL'") case parser.LE, parser.EQ: datum := c.Right.(parser.Datum) key, pErr := encodeTableKey(nil, datum, encoding.Descending) if pErr != nil { panic(pErr) } // Append the constraint to all of the existing spans. for i := range spans { spans[i].start = append(spans[i].start, key...) } case parser.LT: // A "<" constraint is the last start constraint. Since the constraint // is exclusive and the start key is inclusive, we're going to apply // a .PrefixEnd(). Note that a "<" is usually transformed to a "<=". datum := c.Right.(parser.Datum) key, pErr := encodeTableKey(nil, datum, encoding.Descending) if pErr != nil { panic(pErr) } // Append the constraint to all of the existing spans. for i := range spans { spans[i].start = append(spans[i].start, key...) spans[i].start = spans[i].start.PrefixEnd() } default: panic(fmt.Sprintf("unexpected operator: %s", c)) } }
func encodeStartConstraintDescending( spans []span, c *parser.ComparisonExpr) { switch c.Operator { case parser.Is: // An IS NULL expressions allows us to constrain the start of the range // to begin at NULL. if c.Right != parser.DNull { panic("Expected NULL operand for IS operator.") } for i := range spans { spans[i].start = encoding.EncodeNullDescending(spans[i].start) } case parser.LE, parser.EQ: if datum, ok := c.Right.(parser.Datum); ok { key, pErr := encodeTableKey(nil, datum, encoding.Descending) if pErr != nil { panic(pErr) } // Append the constraint to all of the existing spans. for i := range spans { spans[i].start = append(spans[i].start, key...) } } case parser.LT: // A "<" constraint is the last start constraint. Since the constraint // is exclusive and the start key is inclusive, we're going to apply // a .PrefixEnd(). if datum, ok := c.Right.(parser.Datum); ok { key, pErr := encodeTableKey(nil, datum, encoding.Descending) if pErr != nil { panic(pErr) } // Append the constraint to all of the existing spans. for i := range spans { spans[i].start = append(spans[i].start, key...) spans[i].start = spans[i].start.PrefixEnd() } } default: panic(fmt.Errorf("unexpected operator: %s", c.String())) } }
// EncodeTableKey encodes `val` into `b` and returns the new buffer. func EncodeTableKey(b []byte, val parser.Datum, dir encoding.Direction) ([]byte, error) { if (dir != encoding.Ascending) && (dir != encoding.Descending) { return nil, util.Errorf("invalid direction: %d", dir) } if val == parser.DNull { if dir == encoding.Ascending { return encoding.EncodeNullAscending(b), nil } return encoding.EncodeNullDescending(b), nil } switch t := val.(type) { case *parser.DBool: var x int64 if *t { x = 1 } else { x = 0 } if dir == encoding.Ascending { return encoding.EncodeVarintAscending(b, x), nil } return encoding.EncodeVarintDescending(b, x), nil case *parser.DInt: if dir == encoding.Ascending { return encoding.EncodeVarintAscending(b, int64(*t)), nil } return encoding.EncodeVarintDescending(b, int64(*t)), nil case *parser.DFloat: if dir == encoding.Ascending { return encoding.EncodeFloatAscending(b, float64(*t)), nil } return encoding.EncodeFloatDescending(b, float64(*t)), nil case *parser.DDecimal: if dir == encoding.Ascending { return encoding.EncodeDecimalAscending(b, &t.Dec), nil } return encoding.EncodeDecimalDescending(b, &t.Dec), nil case *parser.DString: if dir == encoding.Ascending { return encoding.EncodeStringAscending(b, string(*t)), nil } return encoding.EncodeStringDescending(b, string(*t)), nil case *parser.DBytes: if dir == encoding.Ascending { return encoding.EncodeStringAscending(b, string(*t)), nil } return encoding.EncodeStringDescending(b, string(*t)), nil case *parser.DDate: if dir == encoding.Ascending { return encoding.EncodeVarintAscending(b, int64(*t)), nil } return encoding.EncodeVarintDescending(b, int64(*t)), nil case *parser.DTimestamp: if dir == encoding.Ascending { return encoding.EncodeTimeAscending(b, t.Time), nil } return encoding.EncodeTimeDescending(b, t.Time), nil case *parser.DTimestampTZ: if dir == encoding.Ascending { return encoding.EncodeTimeAscending(b, t.Time), nil } return encoding.EncodeTimeDescending(b, t.Time), nil case *parser.DInterval: if dir == encoding.Ascending { return encoding.EncodeDurationAscending(b, t.Duration) } return encoding.EncodeDurationDescending(b, t.Duration) case *parser.DTuple: for _, datum := range *t { var err error b, err = EncodeTableKey(b, datum, dir) if err != nil { return nil, err } } return b, nil } return nil, util.Errorf("unable to encode table key: %T", val) }
// Encodes `val` into `b` and returns the new buffer. func encodeTableKey(b []byte, val parser.Datum, dir encoding.Direction) ([]byte, *roachpb.Error) { if (dir != encoding.Ascending) && (dir != encoding.Descending) { return nil, roachpb.NewErrorf("invalid direction: %d", dir) } if val == parser.DNull { if dir == encoding.Ascending { return encoding.EncodeNullAscending(b), nil } return encoding.EncodeNullDescending(b), nil } switch t := val.(type) { case parser.DBool: var x int64 if t { x = 1 } else { x = 0 } if dir == encoding.Ascending { return encoding.EncodeVarintAscending(b, x), nil } return encoding.EncodeVarintDescending(b, x), nil case parser.DInt: if dir == encoding.Ascending { return encoding.EncodeVarintAscending(b, int64(t)), nil } return encoding.EncodeVarintDescending(b, int64(t)), nil case parser.DFloat: if dir == encoding.Ascending { return encoding.EncodeFloatAscending(b, float64(t)), nil } return encoding.EncodeFloatDescending(b, float64(t)), nil case parser.DDecimal: if dir == encoding.Ascending { return encoding.EncodeDecimalAscending(b, t.Decimal), nil } return encoding.EncodeDecimalDescending(b, t.Decimal), nil case parser.DString: if dir == encoding.Ascending { return encoding.EncodeStringAscending(b, string(t)), nil } return encoding.EncodeStringDescending(b, string(t)), nil case parser.DBytes: if dir == encoding.Ascending { return encoding.EncodeStringAscending(b, string(t)), nil } return encoding.EncodeStringDescending(b, string(t)), nil case parser.DDate: if dir == encoding.Ascending { return encoding.EncodeVarintAscending(b, int64(t)), nil } return encoding.EncodeVarintDescending(b, int64(t)), nil case parser.DTimestamp: if dir == encoding.Ascending { return encoding.EncodeTimeAscending(b, t.Time), nil } return encoding.EncodeTimeDescending(b, t.Time), nil case parser.DInterval: if dir == encoding.Ascending { return encoding.EncodeVarintAscending(b, int64(t.Duration)), nil } return encoding.EncodeVarintDescending(b, int64(t.Duration)), nil } return nil, roachpb.NewUErrorf("unable to encode table key: %T", val) }