func makeIndexKeyVals(desc *structured.TableDescriptor, index structured.IndexDescriptor) ([]parser.Datum, error) { vals := make([]parser.Datum, len(index.ColumnIDs)) for i, id := range index.ColumnIDs { col, err := desc.FindColumnByID(id) if err != nil { return nil, err } switch col.Type.Kind { case structured.ColumnType_BIT, structured.ColumnType_INT: vals[i] = parser.DInt(0) case structured.ColumnType_FLOAT: vals[i] = parser.DFloat(0) case structured.ColumnType_CHAR, structured.ColumnType_TEXT, structured.ColumnType_BLOB: vals[i] = parser.DString("") default: return nil, util.Errorf("TODO(pmattis): decoded index key: %s", col.Type.Kind) } } if !index.Unique { // Non-unique columns are suffixed by the primary index key. pkVals, err := makeIndexKeyVals(desc, desc.PrimaryIndex) if err != nil { return nil, err } vals = append(vals, pkVals...) } return vals, nil }
func decodeIndexKey(desc *structured.TableDescriptor, index structured.IndexDescriptor, vals map[string]parser.Datum, key []byte) ([]byte, error) { if !bytes.HasPrefix(key, keys.TableDataPrefix) { return nil, fmt.Errorf("%s: invalid key prefix: %q", desc.Name, key) } key = bytes.TrimPrefix(key, keys.TableDataPrefix) var tableID uint64 key, tableID = encoding.DecodeUvarint(key) if uint32(tableID) != desc.ID { return nil, fmt.Errorf("%s: unexpected table ID: %d != %d", desc.Name, desc.ID, tableID) } var indexID uint64 key, indexID = encoding.DecodeUvarint(key) if uint32(indexID) != index.ID { return nil, fmt.Errorf("%s: unexpected index ID: %d != %d", desc.Name, index.ID, indexID) } for _, id := range index.ColumnIDs { col, err := desc.FindColumnByID(id) if err != nil { return nil, err } switch col.Type.Kind { case structured.ColumnType_BIT, structured.ColumnType_INT: var i int64 key, i = encoding.DecodeVarint(key) vals[col.Name] = parser.DInt(i) case structured.ColumnType_FLOAT: var f float64 key, f = encoding.DecodeNumericFloat(key) vals[col.Name] = parser.DFloat(f) case structured.ColumnType_CHAR, structured.ColumnType_TEXT, structured.ColumnType_BLOB: var r []byte key, r = encoding.DecodeBytes(key, nil) vals[col.Name] = parser.DString(r) default: return nil, util.Errorf("TODO(pmattis): decoded index key: %s", col.Type.Kind) } } return key, nil }
// Select selects rows from a single table. func (s *Server) Select(session *Session, p *parser.Select, args []sqlwire.Datum, resp *sqlwire.Response) error { if len(p.Exprs) != 1 { return fmt.Errorf("TODO(pmattis): unsupported select exprs: %s", p.Exprs) } if _, ok := p.Exprs[0].(*parser.StarExpr); !ok { return fmt.Errorf("TODO(pmattis): unsupported select expr: %s", p.Exprs) } if len(p.From) != 1 { return fmt.Errorf("TODO(pmattis): unsupported from: %s", p.From) } var desc *structured.TableDescriptor { ate, ok := p.From[0].(*parser.AliasedTableExpr) if !ok { return fmt.Errorf("TODO(pmattis): unsupported from: %s", p.From) } table, ok := ate.Expr.(parser.QualifiedName) if !ok { return fmt.Errorf("TODO(pmattis): unsupported from: %s", p.From) } var err error desc, err = s.getTableDesc(session.Database, table) if err != nil { return err } } // Retrieve all of the keys that start with our index key prefix. startKey := proto.Key(encodeIndexKeyPrefix(desc.ID, desc.Indexes[0].ID)) endKey := startKey.PrefixEnd() sr, err := s.db.Scan(startKey, endKey, 0) if err != nil { return err } // All of the columns for a particular row will be grouped together. We loop // over the returned key/value pairs and decode the key to extract the // columns encoded within the key and the column ID. We use the column ID to // lookup the column and decode the value. All of these values go into a map // keyed by column name. When the index key changes we output a row // containing the current values. // // The TODOs here are too numerous to list. This is only performing a full // table scan using the primary key. var rows []sqlwire.Result_Row var primaryKey []byte vals := valMap{} for _, kv := range sr { if primaryKey != nil && !bytes.HasPrefix(kv.Key, primaryKey) { if output, err := shouldOutputRow(p.Where, vals); err != nil { return err } else if output { rows = append(rows, outputRow(desc.Columns, vals)) } vals = valMap{} } remaining, err := decodeIndexKey(desc, desc.Indexes[0], vals, kv.Key) if err != nil { return err } primaryKey = []byte(kv.Key[:len(kv.Key)-len(remaining)]) _, colID := encoding.DecodeUvarint(remaining) if err != nil { return err } col, err := desc.FindColumnByID(uint32(colID)) if err != nil { return err } vals[col.Name] = unmarshalValue(*col, kv) if log.V(2) { log.Infof("Scan %q -> %v", kv.Key, vals[col.Name]) } } if output, err := shouldOutputRow(p.Where, vals); err != nil { return err } else if output { rows = append(rows, outputRow(desc.Columns, vals)) } resp.Results = []sqlwire.Result{ { Columns: make([]string, len(desc.Columns)), Rows: rows, }, } for i, col := range desc.Columns { resp.Results[0].Columns[i] = col.Name } return nil }