func TestKeyAddress(t *testing.T) { defer leaktest.AfterTest(t) testCases := []struct { key, expAddress proto.Key }{ {structured.MakeNameMetadataKey(0, "foo"), proto.Key("\x00name-\bfoo")}, {structured.MakeNameMetadataKey(0, "BAR"), proto.Key("\x00name-\bbar")}, {structured.MakeDescMetadataKey(123), proto.Key("\x00desc-\t{")}, } for i, test := range testCases { result := keys.KeyAddress(test.key) if !result.Equal(test.expAddress) { t.Errorf("%d: expected address for key %q doesn't match %q", i, test.key, test.expAddress) } } }
func TestUpdate(t *testing.T) { defer leaktest.AfterTest(t) s, sqlDB, kvDB := setup(t) defer cleanup(s, sqlDB) if _, err := sqlDB.Exec(` CREATE DATABASE t; CREATE TABLE t.kv ( k CHAR PRIMARY KEY, v CHAR, CONSTRAINT a INDEX (k, v), CONSTRAINT b UNIQUE (v) ); INSERT INTO t.kv VALUES ('c', 'e'), ('a', 'c'), ('b', 'd'); `); err != nil { t.Fatal(err) } // The first `MaxReservedDescID` (plus 0) are set aside. nameKey := structured.MakeNameMetadataKey(structured.MaxReservedDescID+1, "kv") gr, err := kvDB.Get(nameKey) if err != nil { t.Fatal(err) } if !gr.Exists() { t.Fatalf("TableDescriptor %q does not exist", nameKey) } descKey := gr.ValueBytes() desc := structured.TableDescriptor{} if err := kvDB.GetProto(descKey, &desc); err != nil { t.Fatal(err) } var tablePrefix []byte tablePrefix = append(tablePrefix, keys.TableDataPrefix...) tablePrefix = encoding.EncodeUvarint(tablePrefix, uint64(desc.ID)) tableStartKey := proto.Key(tablePrefix) tableEndKey := tableStartKey.PrefixEnd() if kvs, err := kvDB.Scan(tableStartKey, tableEndKey, 0); err != nil { t.Fatal(err) } else if l := 12; len(kvs) != l { t.Fatalf("expected %d key value pairs, but got %d", l, len(kvs)) } // Insert that will fail after the index `a` is written. if _, err := sqlDB.Exec(`UPDATE t.kv SET v = 'd' WHERE k = 'c'`); !testutils.IsError(err, "duplicate key value .* violates unique constraint") { t.Fatalf("unexpected error %s", err) } // Verify nothing was written. if kvs, err := kvDB.Scan(tableStartKey, tableEndKey, 0); err != nil { t.Fatal(err) } else if l := 12; len(kvs) != l { t.Fatalf("expected %d key value pairs, but got %d", l, len(kvs)) } }
func TestDelete(t *testing.T) { defer leaktest.AfterTest(t) s, sqlDB, kvDB := setup(t) defer cleanup(s, sqlDB) if _, err := sqlDB.Exec(` CREATE DATABASE t; CREATE TABLE t.kv ( k CHAR PRIMARY KEY, v CHAR, CONSTRAINT a UNIQUE (v) ); INSERT INTO t.kv VALUES ('c', 'e'), ('a', 'c'), ('b', 'd'); `); err != nil { t.Fatal(err) } // The first `MaxReservedDescID` (plus 0) are set aside. nameKey := structured.MakeNameMetadataKey(structured.MaxReservedDescID+1, "kv") gr, err := kvDB.Get(nameKey) if err != nil { t.Fatal(err) } if !gr.Exists() { t.Fatalf("TableDescriptor %q does not exist", nameKey) } descKey := gr.ValueBytes() desc := structured.TableDescriptor{} if err := kvDB.GetProto(descKey, &desc); err != nil { t.Fatal(err) } var tablePrefix []byte tablePrefix = append(tablePrefix, keys.TableDataPrefix...) tablePrefix = encoding.EncodeUvarint(tablePrefix, uint64(desc.ID)) tableStartKey := proto.Key(tablePrefix) tableEndKey := tableStartKey.PrefixEnd() if kvs, err := kvDB.Scan(tableStartKey, tableEndKey, 0); err != nil { t.Fatal(err) } else if l := 9; len(kvs) != l { t.Fatalf("expected %d key value pairs, but got %d", l, len(kvs)) } if _, err := sqlDB.Exec(`DELETE FROM t.kv`); err != nil { t.Fatal(err) } if kvs, err := kvDB.Scan(tableStartKey, tableEndKey, 0); err != nil { t.Fatal(err) } else if l := 0; len(kvs) != l { t.Fatalf("expected %d key value pairs, but got %d", l, len(kvs)) } }
// ShowDatabases returns all the databases. // Privileges: None. // Notes: postgres does not have a "show databases" // mysql has a "SHOW DATABASES" permission, but we have no system-level permissions. func (p *planner) ShowDatabases(n *parser.ShowDatabases) (planNode, error) { prefix := structured.MakeNameMetadataKey(structured.RootNamespaceID, "") sr, err := p.txn.Scan(prefix, prefix.PrefixEnd(), 0) if err != nil { return nil, err } v := &valuesNode{columns: []string{"Database"}} for _, row := range sr { name := string(bytes.TrimPrefix(row.Key, prefix)) v.rows = append(v.rows, []parser.Datum{parser.DString(name)}) } return v, nil }
// DropDatabase drops a database. // Privileges: WRITE on database. // Notes: postgres allows only the database owner to DROP a database. // mysql requires the DROP privileges on the database. // TODO(XisiHuang): our DROP DATABASE is like the postgres DROP SCHEMA // (cockroach database == postgres schema). the postgres default of not // dropping the schema if there are dependent objects is more sensible // (see the RESTRICT and CASCADE options). func (p *planner) DropDatabase(n *parser.DropDatabase) (planNode, error) { if n.Name == "" { return nil, errEmptyDatabaseName } nameKey := structured.MakeNameMetadataKey(structured.RootNamespaceID, string(n.Name)) gr, err := p.txn.Get(nameKey) if err != nil { return nil, err } if !gr.Exists() { if n.IfExists { // Noop. return &valuesNode{}, nil } return nil, fmt.Errorf("database %q does not exist", n.Name) } descKey := gr.ValueBytes() desc := structured.DatabaseDescriptor{} if err := p.txn.GetProto(descKey, &desc); err != nil { return nil, err } if err := desc.Validate(); err != nil { return nil, err } if !desc.HasPrivilege(p.user, parser.PrivilegeWrite) { return nil, fmt.Errorf("user %s does not have %s privilege on database %s", p.user, parser.PrivilegeWrite, desc.Name) } tbNames, err := p.getTableNames(&desc) if err != nil { return nil, err } if _, err := p.DropTable(&parser.DropTable{Names: tbNames}); err != nil { return nil, err } b := &client.Batch{} b.Del(descKey) b.Del(nameKey) if err := p.txn.Run(b); err != nil { return nil, err } return &valuesNode{}, nil }
func (p *planner) getTableNames(dbDesc *structured.DatabaseDescriptor) (parser.QualifiedNames, error) { prefix := structured.MakeNameMetadataKey(dbDesc.ID, "") sr, err := p.db.Scan(prefix, prefix.PrefixEnd(), 0) if err != nil { return nil, err } var qualifiedNames parser.QualifiedNames for _, row := range sr { tableName := string(bytes.TrimPrefix(row.Key, prefix)) qualifiedNames = append(qualifiedNames, &parser.QualifiedName{ Base: parser.Name(dbDesc.Name), Indirect: parser.Indirection{parser.NameIndirection(tableName)}, }) } return qualifiedNames, nil }
func TestDatabaseDescriptor(t *testing.T) { defer leaktest.AfterTest(t) s, sqlDB, kvDB := setup(t) defer cleanup(s, sqlDB) // The first `MaxReservedDescID` (plus 0) are set aside. expectedCounter := int64(structured.MaxReservedDescID + 1) // Test values before creating the database. // descriptor ID counter. if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil { t.Fatal(err) } else if actual := ir.ValueInt(); actual != expectedCounter { t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, actual) } // Database name. nameKey := structured.MakeNameMetadataKey(structured.RootNamespaceID, "test") if gr, err := kvDB.Get(nameKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatal("expected non-existing key") } // Write some junk that is going to interfere with table creation. dbDescKey := structured.MakeDescMetadataKey(structured.ID(expectedCounter)) if err := kvDB.CPut(dbDescKey, "foo", nil); err != nil { t.Fatal(err) } // Table creation should fail, and nothing should have been written. if _, err := sqlDB.Exec(`CREATE DATABASE test`); !testutils.IsError(err, "unexpected value") { t.Fatalf("unexpected error %s", err) } if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil { t.Fatal(err) } else if actual := ir.ValueInt(); actual != expectedCounter { t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, actual) } if kvs, err := kvDB.Scan(keys.NameMetadataPrefix, keys.NameMetadataPrefix.PrefixEnd(), 0); err != nil { t.Fatal(err) } else { if a, e := len(kvs), 0; a != e { t.Fatalf("expected %d keys to have been written, found %d keys", e, a) } } // Remove the junk; allow table creation to proceed. if err := kvDB.Del(dbDescKey); err != nil { t.Fatal(err) } if _, err := sqlDB.Exec(`CREATE DATABASE test`); err != nil { t.Fatal(err) } expectedCounter++ // Check keys again. // descriptor ID counter. if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil { t.Fatal(err) } else if actual := ir.ValueInt(); actual != expectedCounter { t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, actual) } // Database name. if gr, err := kvDB.Get(nameKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatal("key is missing") } // database descriptor. if gr, err := kvDB.Get(dbDescKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatal("key is missing") } // Now try to create it again. We should fail, but not increment the counter. if _, err := sqlDB.Exec(`CREATE DATABASE test`); err == nil { t.Fatal("failure expected") } // Check keys again. // descriptor ID counter. if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil { t.Fatal(err) } else if actual := ir.ValueInt(); actual != expectedCounter { t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, actual) } // Database name. if gr, err := kvDB.Get(nameKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatal("key is missing") } // database descriptor. if gr, err := kvDB.Get(dbDescKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatal("key is missing") } }
func TestDatabaseDescriptor(t *testing.T) { defer leaktest.AfterTest(t) s, sqlDB, kvDB := setup(t) defer cleanup(s, sqlDB) // The first `MaxReservedDescID` (plus 0) are set aside. expectedCounter := int64(structured.MaxReservedDescID + 1) // Test values before creating the database. // descriptor ID counter. if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil { t.Fatal(err) } else if ir.ValueInt() != expectedCounter { t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, ir.ValueInt()) } // Database name. nameKey := structured.MakeNameMetadataKey(structured.RootNamespaceID, "test") if gr, err := kvDB.Get(nameKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatal("expected non-existing key") } if _, err := sqlDB.Exec(`CREATE DATABASE test`); err != nil { t.Fatal(err) } expectedCounter++ // Check keys again. // descriptor ID counter. if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil { t.Fatal(err) } else if ir.ValueInt() != expectedCounter { t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, ir.ValueInt()) } // Database name. if gr, err := kvDB.Get(nameKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatal("key is missing") } // database descriptor. descKey := structured.MakeDescMetadataKey(structured.ID(expectedCounter - 1)) if gr, err := kvDB.Get(descKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatal("key is missing") } // Now try to create it again. We should fail, but not increment the counter. if _, err := sqlDB.Exec(`CREATE DATABASE test`); err == nil { t.Fatal("failure expected") } // Check keys again. // descriptor ID counter. if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil { t.Fatal(err) } else if ir.ValueInt() != expectedCounter { t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, ir.ValueInt()) } // Database name. if gr, err := kvDB.Get(nameKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatal("key is missing") } // database descriptor. if gr, err := kvDB.Get(descKey); err != nil { t.Fatal(err) } else if !gr.Exists() { t.Fatal("key is missing") } }
func (tk tableKey) Key() proto.Key { return structured.MakeNameMetadataKey(tk.id, tk.name) }
func TestDropDatabase(t *testing.T) { defer leaktest.AfterTest(t) s, sqlDB, kvDB := setup(t) defer cleanup(s, sqlDB) if _, err := sqlDB.Exec(` CREATE DATABASE t; CREATE TABLE t.kv (k CHAR PRIMARY KEY, v CHAR); INSERT INTO t.kv VALUES ('c', 'e'), ('a', 'c'), ('b', 'd'); `); err != nil { t.Fatal(err) } dbNameKey := structured.MakeNameMetadataKey(structured.RootNamespaceID, "t") r, err := kvDB.Get(dbNameKey) if err != nil { t.Fatal(err) } if !r.Exists() { t.Fatalf(`database "t" does not exist`) } dbDescKey := r.ValueBytes() dbDesc := structured.DatabaseDescriptor{} if err := kvDB.GetProto(dbDescKey, &dbDesc); err != nil { t.Fatal(err) } tbNameKey := structured.MakeNameMetadataKey(dbDesc.ID, "kv") gr, err := kvDB.Get(tbNameKey) if err != nil { t.Fatal(err) } if !gr.Exists() { t.Fatalf(`table "kv" does not exist`) } tbDescKey := gr.ValueBytes() tbDesc := structured.TableDescriptor{} if err := kvDB.GetProto(tbDescKey, &tbDesc); err != nil { t.Fatal(err) } var tablePrefix []byte tablePrefix = append(tablePrefix, keys.TableDataPrefix...) tablePrefix = encoding.EncodeUvarint(tablePrefix, uint64(tbDesc.ID)) tableStartKey := proto.Key(tablePrefix) tableEndKey := tableStartKey.PrefixEnd() if kvs, err := kvDB.Scan(tableStartKey, tableEndKey, 0); err != nil { t.Fatal(err) } else if l := 6; len(kvs) != l { t.Fatalf("expected %d key value pairs, but got %d", l, len(kvs)) } if _, err := sqlDB.Exec(`DROP DATABASE t`); err != nil { t.Fatal(err) } if kvs, err := kvDB.Scan(tableStartKey, tableEndKey, 0); err != nil { t.Fatal(err) } else if l := 0; len(kvs) != l { t.Fatalf("expected %d key value pairs, but got %d", l, len(kvs)) } if gr, err := kvDB.Get(tbDescKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("table descriptor still exists after database is dropped") } if gr, err := kvDB.Get(tbNameKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("table descriptor key still exists after database is dropped") } if gr, err := kvDB.Get(dbDescKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("database descriptor still exists after database is dropped") } if gr, err := kvDB.Get(dbNameKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("database descriptor key still exists after database is dropped") } }
func TestDropTable(t *testing.T) { defer leaktest.AfterTest(t) s, sqlDB, kvDB := setup(t) defer cleanup(s, sqlDB) if _, err := sqlDB.Exec("CREATE DATABASE t"); err != nil { t.Fatal(err) } if _, err := sqlDB.Exec("CREATE TABLE t.kv (k CHAR PRIMARY KEY, v CHAR)"); err != nil { t.Fatal(err) } if _, err := sqlDB.Exec(`INSERT INTO t.kv VALUES ('c', 'e'), ('a', 'c'),('b', 'd')`); err != nil { t.Fatal(err) } // The first `MaxReservedDescID` (plus 0) are set aside. expectedDBCounter := uint32(structured.MaxReservedDescID + 1) nameKey := structured.MakeNameMetadataKey(structured.ID(expectedDBCounter), "kv") gr, err := kvDB.Get(nameKey) if err != nil { t.Fatal(err) } if !gr.Exists() { t.Fatalf("TableDescriptor %q does not exist", nameKey) } descKey := gr.ValueBytes() desc := structured.TableDescriptor{} if err := kvDB.GetProto(descKey, &desc); err != nil { t.Fatal(err) } var tablePrefix []byte tablePrefix = append(tablePrefix, keys.TableDataPrefix...) tablePrefix = encoding.EncodeUvarint(tablePrefix, uint64(desc.ID)) tableStartKey := proto.Key(tablePrefix) tableEndKey := tableStartKey.PrefixEnd() if kvs, err := kvDB.Scan(tableStartKey, tableEndKey, 0); err != nil { t.Fatal(err) } else if l := 6; len(kvs) != l { t.Fatalf("expected %d key value pairs, but got %d", l, len(kvs)) } if _, err := sqlDB.Exec("DROP TABLE t.kv"); err != nil { t.Fatal(err) } if kvs, err := kvDB.Scan(tableStartKey, tableEndKey, 0); err != nil { t.Fatal(err) } else if l := 0; len(kvs) != l { t.Fatalf("expected %d key value pairs, but got %d", l, len(kvs)) } if gr, err := kvDB.Get(descKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("table descriptor still exists after the table is dropped") } if gr, err := kvDB.Get(nameKey); err != nil { t.Fatal(err) } else if gr.Exists() { t.Fatalf("table namekey still exists after the table is dropped") } }
func (dk databaseKey) Key() proto.Key { return structured.MakeNameMetadataKey(structured.RootNamespaceID, dk.name) }