1
0
Fork 0

Merge pull request #1337 from rqlite/store-load-from-reader

Store can load from an io.Reader
master
Philip O'Toole 1 year ago committed by GitHub
commit 28127dec20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,3 +1,7 @@
## 7.21.5 (unreleased)
### Implementation changes and bug fixes
- [PR #1337](https://github.com/rqlite/rqlite/pull/1337): Store can now load from an io.Reader.
## 7.21.4 (July 8th 2023)
### Implementation changes and bug fixes
- [PR #1336](https://github.com/rqlite/rqlite/pull/1336): Remove on-disk-startup control. It's no longer needed as on-disk performance is now very close to in-memory performance, thanks to the switch to _synchronous off_ mode and the use of the SQLite WAL.

@ -1143,6 +1143,27 @@ func (s *Store) Provide(path string) error {
return nil
}
// LoadFromReader loads SQLite data, as read from r, into the database, sending the
// request through the Raft log.
func (s *Store) LoadFromReader(r io.Reader) error {
if !s.open {
return ErrNotOpen
}
if !s.Ready() {
return ErrNotReady
}
b, err := io.ReadAll(r)
if err != nil {
return err
}
lr := &command.LoadRequest{
Data: b,
}
return s.load(lr)
}
// Loads an entire SQLite file into the database, sending the request
// through the Raft log.
func (s *Store) Load(lr *command.LoadRequest) error {

@ -975,6 +975,95 @@ COMMIT;
}
}
func Test_SingleNodeLoadBinaryFromReader(t *testing.T) {
s, ln := mustNewStore(t, true)
defer ln.Close()
if err := s.Open(); err != nil {
t.Fatalf("failed to open single-node store: %s", err.Error())
}
if err := s.Bootstrap(NewServer(s.ID(), s.Addr(), true)); err != nil {
t.Fatalf("failed to bootstrap single-node store: %s", err.Error())
}
defer s.Close(true)
if _, err := s.WaitForLeader(10 * time.Second); err != nil {
t.Fatalf("Error waiting for leader: %s", err)
}
// Load a dataset, to check it's erased by the SQLite file load.
dump := `PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE bar (id integer not null primary key, name text);
INSERT INTO "bar" VALUES(1,'declan');
COMMIT;
`
_, err := s.Execute(executeRequestFromString(dump, false, false))
if err != nil {
t.Fatalf("failed to load simple dump: %s", err.Error())
}
// Check that data were loaded correctly.
qr := queryRequestFromString("SELECT * FROM bar", false, true)
qr.Level = command.QueryRequest_QUERY_REQUEST_LEVEL_STRONG
r, err := s.Query(qr)
if err != nil {
t.Fatalf("failed to query single node: %s", err.Error())
}
if exp, got := `["id","name"]`, asJSON(r[0].Columns); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
if exp, got := `[[1,"declan"]]`, asJSON(r[0].Values); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
f, err := os.Open(filepath.Join("testdata", "load.sqlite"))
if err != nil {
t.Fatalf("failed to open SQLite file: %s", err.Error())
}
defer f.Close()
err = s.LoadFromReader(f)
if err != nil {
t.Fatalf("failed to load SQLite file via Reader: %s", err.Error())
}
// Check that data were loaded correctly.
qr = queryRequestFromString("SELECT * FROM foo WHERE id=2", false, true)
qr.Level = command.QueryRequest_QUERY_REQUEST_LEVEL_STRONG
r, err = s.Query(qr)
if err != nil {
t.Fatalf("failed to query single node: %s", err.Error())
}
if exp, got := `["id","name"]`, asJSON(r[0].Columns); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
if exp, got := `[[2,"fiona"]]`, asJSON(r[0].Values); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
qr = queryRequestFromString("SELECT count(*) FROM foo", false, true)
qr.Level = command.QueryRequest_QUERY_REQUEST_LEVEL_STRONG
r, err = s.Query(qr)
if err != nil {
t.Fatalf("failed to query single node: %s", err.Error())
}
if exp, got := `["count(*)"]`, asJSON(r[0].Columns); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
if exp, got := `[[3]]`, asJSON(r[0].Values); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
// Check pre-existing data is gone.
qr = queryRequestFromString("SELECT * FROM bar", false, true)
qr.Level = command.QueryRequest_QUERY_REQUEST_LEVEL_STRONG
r, err = s.Query(qr)
if err != nil {
t.Fatalf("failed to query single node: %s", err.Error())
}
if exp, got := `{"error":"no such table: bar"}`, asJSON(r[0]); exp != got {
t.Fatalf("unexpected results for query\nexp: %s\ngot: %s", exp, got)
}
}
func Test_SingleNodeAutoRestore(t *testing.T) {
s, ln := mustNewStore(t, true)
defer ln.Close()

Loading…
Cancel
Save