Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package rqlite for openSUSE:Factory checked in at 2025-04-22 17:27:08 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rqlite (Old) and /work/SRC/openSUSE:Factory/.rqlite.new.30101 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rqlite" Tue Apr 22 17:27:08 2025 rev:13 rq:1271071 version:8.36.18 Changes: -------- --- /work/SRC/openSUSE:Factory/rqlite/rqlite.changes 2025-04-04 17:30:15.634878545 +0200 +++ /work/SRC/openSUSE:Factory/.rqlite.new.30101/rqlite.changes 2025-04-22 17:27:34.753309024 +0200 @@ -1,0 +2,8 @@ +Sun Apr 20 13:04:48 UTC 2025 - Andreas Stieger <andreas.stie...@gmx.de> + +- Update to version 8.36.18: + * Follow redirects when building sqlite-vec + * Support Commit Hook registration + * Support registering Update Hooks at the database level + +------------------------------------------------------------------- Old: ---- rqlite-8.36.16.tar.xz New: ---- rqlite-8.36.18.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rqlite.spec ++++++ --- /var/tmp/diff_new_pack.3Eyr8n/_old 2025-04-22 17:27:35.341333717 +0200 +++ /var/tmp/diff_new_pack.3Eyr8n/_new 2025-04-22 17:27:35.345333886 +0200 @@ -17,7 +17,7 @@ Name: rqlite -Version: 8.36.16 +Version: 8.36.18 Release: 0 Summary: Distributed relational database built on SQLite License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.3Eyr8n/_old 2025-04-22 17:27:35.385335565 +0200 +++ /var/tmp/diff_new_pack.3Eyr8n/_new 2025-04-22 17:27:35.389335733 +0200 @@ -3,7 +3,7 @@ <param name="url">https://github.com/rqlite/rqlite.git</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v8.36.16</param> + <param name="revision">v8.36.18</param> <param name="versionformat">@PARENT_TAG@</param> <param name="changesgenerate">enable</param> <param name="versionrewrite-pattern">v(.*)</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.3Eyr8n/_old 2025-04-22 17:27:35.409336573 +0200 +++ /var/tmp/diff_new_pack.3Eyr8n/_new 2025-04-22 17:27:35.413336741 +0200 @@ -1,7 +1,7 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/rqlite/rqlite.git</param> - <param name="changesrevision">34eb2bfd3ec7a67f3617dfa0944251197030c8e6</param> + <param name="changesrevision">8fac7ad21e246ad79222aed1bef881110c41b4ed</param> </service> </servicedata> (No newline at EOF) ++++++ rqlite-8.36.16.tar.xz -> rqlite-8.36.18.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rqlite-8.36.16/CHANGELOG.md new/rqlite-8.36.18/CHANGELOG.md --- old/rqlite-8.36.16/CHANGELOG.md 2025-04-03 19:35:09.000000000 +0200 +++ new/rqlite-8.36.18/CHANGELOG.md 2025-04-19 14:35:27.000000000 +0200 @@ -1,4 +1,17 @@ -## v8.36.16 (April 32rd 2025) +## v8.36.18 (April 19th 2025) +There are no functional changes to rqlite in this release. The only changes are fixes for Docker image creation. +### Implementation changes and bug fixes +- [96f603d](https://github.com/rqlite/rqlite/commit/96f603d74c4d0f94949fbc596244606baaf557d9): Enable `curl` redirects when building _sqlite-vec_ to address [Docker build failures](https://github.com/rqlite/rqlite/actions/runs/14545179069). + +## v8.36.17 (April 18th 2025) +### Implementation changes and bug fixes +- [PR #2061](https://github.com/rqlite/rqlite/pull/2061): Support registering Update Hooks at the database level. +- [PR #2062](https://github.com/rqlite/rqlite/pull/2062): Support registering Commit Hooks at the database level. +- [PR #2066](https://github.com/rqlite/rqlite/pull/2066): Update dependencies. +- [PR #2067](https://github.com/rqlite/rqlite/pull/2067): Update SQLite to 3.49.1. + +## v8.36.16 (April 3rd 2025) +There are no functional changes to rqlite in this release. The only changes are improvements to the Docker image. ### Implementation changes and bug fixes - [64f7ef7](https://github.com/rqlite/rqlite/commit/64f7ef7f738c9973770c3620a65692b538a49a3a): Docker image supports enabling Foreign Key constraints via an Environment variable. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rqlite-8.36.16/Dockerfile new/rqlite-8.36.18/Dockerfile --- old/rqlite-8.36.16/Dockerfile 2025-04-03 19:35:09.000000000 +0200 +++ new/rqlite-8.36.18/Dockerfile 2025-04-19 14:35:27.000000000 +0200 @@ -40,6 +40,7 @@ RUN curl -L `curl -s https://api.github.com/repos/asg017/sqlite-vec/releases/latest | grep "tarball_url" | cut -d '"' -f 4` -o sqlite-vec.tar.gz && \ tar xvfz sqlite-vec.tar.gz && \ + echo location >> ~/.curlrc && \ cd asg017* && sh scripts/vendor.sh && echo "#include <sys/types.h>" | cat - sqlite-vec.c > temp && mv temp sqlite-vec.c && make loadable && zip -j /extensions/sqlite-vec.zip dist/vec0.so RUN git clone https://github.com/rqlite/rqlite-sqlite-ext.git diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rqlite-8.36.16/command/proto/command.pb.go new/rqlite-8.36.18/command/proto/command.pb.go --- old/rqlite-8.36.16/command/proto/command.pb.go 2025-04-03 19:35:09.000000000 +0200 +++ new/rqlite-8.36.18/command/proto/command.pb.go 2025-04-19 14:35:27.000000000 +0200 @@ -241,6 +241,58 @@ return file_command_proto_rawDescGZIP(), []int{20, 0} } +type UpdateHookEvent_Operation int32 + +const ( + UpdateHookEvent_UNKNOWN UpdateHookEvent_Operation = 0 + UpdateHookEvent_INSERT UpdateHookEvent_Operation = 1 + UpdateHookEvent_UPDATE UpdateHookEvent_Operation = 2 + UpdateHookEvent_DELETE UpdateHookEvent_Operation = 3 +) + +// Enum value maps for UpdateHookEvent_Operation. +var ( + UpdateHookEvent_Operation_name = map[int32]string{ + 0: "UNKNOWN", + 1: "INSERT", + 2: "UPDATE", + 3: "DELETE", + } + UpdateHookEvent_Operation_value = map[string]int32{ + "UNKNOWN": 0, + "INSERT": 1, + "UPDATE": 2, + "DELETE": 3, + } +) + +func (x UpdateHookEvent_Operation) Enum() *UpdateHookEvent_Operation { + p := new(UpdateHookEvent_Operation) + *p = x + return p +} + +func (x UpdateHookEvent_Operation) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (UpdateHookEvent_Operation) Descriptor() protoreflect.EnumDescriptor { + return file_command_proto_enumTypes[4].Descriptor() +} + +func (UpdateHookEvent_Operation) Type() protoreflect.EnumType { + return &file_command_proto_enumTypes[4] +} + +func (x UpdateHookEvent_Operation) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use UpdateHookEvent_Operation.Descriptor instead. +func (UpdateHookEvent_Operation) EnumDescriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{21, 0} +} + type Parameter struct { state protoimpl.MessageState `protogen:"open.v1"` // Types that are valid to be assigned to Value: @@ -1711,6 +1763,74 @@ return nil } +type UpdateHookEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` + Op UpdateHookEvent_Operation `protobuf:"varint,2,opt,name=op,proto3,enum=command.UpdateHookEvent_Operation" json:"op,omitempty"` + Table string `protobuf:"bytes,3,opt,name=table,proto3" json:"table,omitempty"` + RowId int64 `protobuf:"varint,4,opt,name=row_id,json=rowId,proto3" json:"row_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateHookEvent) Reset() { + *x = UpdateHookEvent{} + mi := &file_command_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateHookEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateHookEvent) ProtoMessage() {} + +func (x *UpdateHookEvent) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateHookEvent.ProtoReflect.Descriptor instead. +func (*UpdateHookEvent) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{21} +} + +func (x *UpdateHookEvent) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +func (x *UpdateHookEvent) GetOp() UpdateHookEvent_Operation { + if x != nil { + return x.Op + } + return UpdateHookEvent_UNKNOWN +} + +func (x *UpdateHookEvent) GetTable() string { + if x != nil { + return x.Table + } + return "" +} + +func (x *UpdateHookEvent) GetRowId() int64 { + if x != nil { + return x.RowId + } + return 0 +} + var File_command_proto protoreflect.FileDescriptor const file_command_proto_rawDesc = "" + @@ -1850,6 +1970,19 @@ "\n" + "\x06UPDATE\x10\x02\x12\n" + "\n" + + "\x06DELETE\x10\x03\"\xc6\x01\n" + + "\x0fUpdateHookEvent\x12\x14\n" + + "\x05error\x18\x01 \x01(\tR\x05error\x122\n" + + "\x02op\x18\x02 \x01(\x0e2\".command.UpdateHookEvent.OperationR\x02op\x12\x14\n" + + "\x05table\x18\x03 \x01(\tR\x05table\x12\x15\n" + + "\x06row_id\x18\x04 \x01(\x03R\x05rowId\"<\n" + + "\tOperation\x12\v\n" + + "\aUNKNOWN\x10\x00\x12\n" + + "\n" + + "\x06INSERT\x10\x01\x12\n" + + "\n" + + "\x06UPDATE\x10\x02\x12\n" + + "\n" + "\x06DELETE\x10\x03B+Z)github.com/rqlite/rqlite/v8/command/protob\x06proto3" var ( @@ -1864,58 +1997,61 @@ return file_command_proto_rawDescData } -var file_command_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_command_proto_msgTypes = make([]protoimpl.MessageInfo, 21) +var file_command_proto_enumTypes = make([]protoimpl.EnumInfo, 5) +var file_command_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_command_proto_goTypes = []any{ - (QueryRequest_Level)(0), // 0: command.QueryRequest.Level - (BackupRequest_Format)(0), // 1: command.BackupRequest.Format - (Command_Type)(0), // 2: command.Command.Type - (CDCEvent_Operation)(0), // 3: command.CDCEvent.Operation - (*Parameter)(nil), // 4: command.Parameter - (*Statement)(nil), // 5: command.Statement - (*Request)(nil), // 6: command.Request - (*QueryRequest)(nil), // 7: command.QueryRequest - (*Values)(nil), // 8: command.Values - (*QueryRows)(nil), // 9: command.QueryRows - (*ExecuteRequest)(nil), // 10: command.ExecuteRequest - (*ExecuteResult)(nil), // 11: command.ExecuteResult - (*ExecuteQueryRequest)(nil), // 12: command.ExecuteQueryRequest - (*ExecuteQueryResponse)(nil), // 13: command.ExecuteQueryResponse - (*BackupRequest)(nil), // 14: command.BackupRequest - (*LoadRequest)(nil), // 15: command.LoadRequest - (*LoadChunkRequest)(nil), // 16: command.LoadChunkRequest - (*JoinRequest)(nil), // 17: command.JoinRequest - (*NotifyRequest)(nil), // 18: command.NotifyRequest - (*RemoveNodeRequest)(nil), // 19: command.RemoveNodeRequest - (*Noop)(nil), // 20: command.Noop - (*Command)(nil), // 21: command.Command - (*CDCValue)(nil), // 22: command.CDCValue - (*CDCRow)(nil), // 23: command.CDCRow - (*CDCEvent)(nil), // 24: command.CDCEvent + (QueryRequest_Level)(0), // 0: command.QueryRequest.Level + (BackupRequest_Format)(0), // 1: command.BackupRequest.Format + (Command_Type)(0), // 2: command.Command.Type + (CDCEvent_Operation)(0), // 3: command.CDCEvent.Operation + (UpdateHookEvent_Operation)(0), // 4: command.UpdateHookEvent.Operation + (*Parameter)(nil), // 5: command.Parameter + (*Statement)(nil), // 6: command.Statement + (*Request)(nil), // 7: command.Request + (*QueryRequest)(nil), // 8: command.QueryRequest + (*Values)(nil), // 9: command.Values + (*QueryRows)(nil), // 10: command.QueryRows + (*ExecuteRequest)(nil), // 11: command.ExecuteRequest + (*ExecuteResult)(nil), // 12: command.ExecuteResult + (*ExecuteQueryRequest)(nil), // 13: command.ExecuteQueryRequest + (*ExecuteQueryResponse)(nil), // 14: command.ExecuteQueryResponse + (*BackupRequest)(nil), // 15: command.BackupRequest + (*LoadRequest)(nil), // 16: command.LoadRequest + (*LoadChunkRequest)(nil), // 17: command.LoadChunkRequest + (*JoinRequest)(nil), // 18: command.JoinRequest + (*NotifyRequest)(nil), // 19: command.NotifyRequest + (*RemoveNodeRequest)(nil), // 20: command.RemoveNodeRequest + (*Noop)(nil), // 21: command.Noop + (*Command)(nil), // 22: command.Command + (*CDCValue)(nil), // 23: command.CDCValue + (*CDCRow)(nil), // 24: command.CDCRow + (*CDCEvent)(nil), // 25: command.CDCEvent + (*UpdateHookEvent)(nil), // 26: command.UpdateHookEvent } var file_command_proto_depIdxs = []int32{ - 4, // 0: command.Statement.parameters:type_name -> command.Parameter - 5, // 1: command.Request.statements:type_name -> command.Statement - 6, // 2: command.QueryRequest.request:type_name -> command.Request + 5, // 0: command.Statement.parameters:type_name -> command.Parameter + 6, // 1: command.Request.statements:type_name -> command.Statement + 7, // 2: command.QueryRequest.request:type_name -> command.Request 0, // 3: command.QueryRequest.level:type_name -> command.QueryRequest.Level - 4, // 4: command.Values.parameters:type_name -> command.Parameter - 8, // 5: command.QueryRows.values:type_name -> command.Values - 6, // 6: command.ExecuteRequest.request:type_name -> command.Request - 6, // 7: command.ExecuteQueryRequest.request:type_name -> command.Request + 5, // 4: command.Values.parameters:type_name -> command.Parameter + 9, // 5: command.QueryRows.values:type_name -> command.Values + 7, // 6: command.ExecuteRequest.request:type_name -> command.Request + 7, // 7: command.ExecuteQueryRequest.request:type_name -> command.Request 0, // 8: command.ExecuteQueryRequest.level:type_name -> command.QueryRequest.Level - 9, // 9: command.ExecuteQueryResponse.q:type_name -> command.QueryRows - 11, // 10: command.ExecuteQueryResponse.e:type_name -> command.ExecuteResult + 10, // 9: command.ExecuteQueryResponse.q:type_name -> command.QueryRows + 12, // 10: command.ExecuteQueryResponse.e:type_name -> command.ExecuteResult 1, // 11: command.BackupRequest.format:type_name -> command.BackupRequest.Format 2, // 12: command.Command.type:type_name -> command.Command.Type - 22, // 13: command.CDCRow.values:type_name -> command.CDCValue + 23, // 13: command.CDCRow.values:type_name -> command.CDCValue 3, // 14: command.CDCEvent.op:type_name -> command.CDCEvent.Operation - 23, // 15: command.CDCEvent.old_row:type_name -> command.CDCRow - 23, // 16: command.CDCEvent.new_row:type_name -> command.CDCRow - 17, // [17:17] is the sub-list for method output_type - 17, // [17:17] is the sub-list for method input_type - 17, // [17:17] is the sub-list for extension type_name - 17, // [17:17] is the sub-list for extension extendee - 0, // [0:17] is the sub-list for field type_name + 24, // 15: command.CDCEvent.old_row:type_name -> command.CDCRow + 24, // 16: command.CDCEvent.new_row:type_name -> command.CDCRow + 4, // 17: command.UpdateHookEvent.op:type_name -> command.UpdateHookEvent.Operation + 18, // [18:18] is the sub-list for method output_type + 18, // [18:18] is the sub-list for method input_type + 18, // [18:18] is the sub-list for extension type_name + 18, // [18:18] is the sub-list for extension extendee + 0, // [0:18] is the sub-list for field type_name } func init() { file_command_proto_init() } @@ -1947,8 +2083,8 @@ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_command_proto_rawDesc), len(file_command_proto_rawDesc)), - NumEnums: 4, - NumMessages: 21, + NumEnums: 5, + NumMessages: 22, NumExtensions: 0, NumServices: 0, }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rqlite-8.36.16/command/proto/command.proto new/rqlite-8.36.18/command/proto/command.proto --- old/rqlite-8.36.16/command/proto/command.proto 2025-04-03 19:35:09.000000000 +0200 +++ new/rqlite-8.36.18/command/proto/command.proto 2025-04-19 14:35:27.000000000 +0200 @@ -171,3 +171,16 @@ CDCRow old_row = 6; CDCRow new_row = 7; } + +message UpdateHookEvent { + enum Operation { + UNKNOWN = 0; + INSERT = 1; + UPDATE = 2; + DELETE = 3; + } + string error = 1; + Operation op = 2; + string table = 3; + int64 row_id = 4; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rqlite-8.36.16/db/db.go new/rqlite-8.36.18/db/db.go --- old/rqlite-8.36.16/db/db.go 2025-04-03 19:35:09.000000000 +0200 +++ new/rqlite-8.36.18/db/db.go 2025-04-19 14:35:27.000000000 +0200 @@ -52,6 +52,10 @@ numPreupdates = "preupdates" numPreupdatesErrors = "preupdates_errors" numPreupdatesCBErrors = "preupdates_callback_errors" + numUpdateHooks = "update_hooks" + numUpdateHooksCBErrors = "update_hooks_callback_errors" + numUpdateHooksErrors = "update_hooks_errors" + numCommitHooks = "commit_hooks" ) var ( @@ -119,6 +123,10 @@ stats.Add(numPreupdates, 0) stats.Add(numPreupdatesErrors, 0) stats.Add(numPreupdatesCBErrors, 0) + stats.Add(numUpdateHooks, 0) + stats.Add(numUpdateHooksCBErrors, 0) + stats.Add(numUpdateHooksErrors, 0) + stats.Add(numCommitHooks, 0) } // DB is the SQL database. @@ -316,12 +324,108 @@ } } } - f := func(driverConn interface{}) error { + f := func(driverConn any) error { conn := driverConn.(*sqlite3.SQLiteConn) conn.RegisterPreUpdateHook(cb) return nil } + conn, err := db.rwDB.Conn(context.Background()) + if err != nil { + return err + } + defer conn.Close() + if err := conn.Raw(f); err != nil { + return err + } + return nil +} + +// UpdateHookCallback is a callback function that is called before a row is modified +// in the database. +type UpdateHookCallback func(ev *command.UpdateHookEvent) error + +// RegisterUpdateHook registers a callback that is called when a row is modified +// in the database. If a callback is already registered, it is replaced. If hook is nil, +// the callback is removed. +func (db *DB) RegisterUpdateHook(hook UpdateHookCallback) error { + // Convert from SQLite hook data to rqlite hook data. + convertFn := func(op int, _, table string, rowID int64) (*command.UpdateHookEvent, error) { + he := &command.UpdateHookEvent{ + Table: table, + RowId: rowID, + } + + switch op { + case sqlite3.SQLITE_INSERT: + he.Op = command.UpdateHookEvent_INSERT + case sqlite3.SQLITE_UPDATE: + he.Op = command.UpdateHookEvent_UPDATE + case sqlite3.SQLITE_DELETE: + he.Op = command.UpdateHookEvent_DELETE + default: + return nil, fmt.Errorf("unknown update hook operation %d", op) + } + return he, nil + } + + // Register the callback with the SQLite connection. + var cb func(int, string, string, int64) + if hook != nil { + cb = func(op int, dbName, tblName string, rowID int64) { + stats.Add(numUpdateHooks, 1) + ev, err := convertFn(op, dbName, tblName, rowID) + if err != nil { + stats.Add(numUpdateHooks, 1) + ev.Error = err.Error() + } + if err := hook(ev); err != nil { + stats.Add(numUpdateHooksCBErrors, 1) + } + } + } + f := func(driverConn any) error { + conn := driverConn.(*sqlite3.SQLiteConn) + conn.RegisterUpdateHook(cb) + return nil + } + + conn, err := db.rwDB.Conn(context.Background()) + if err != nil { + return err + } + defer conn.Close() + if err := conn.Raw(f); err != nil { + return err + } + return nil +} + +// CommitHookCallback is a callback function that is called whenever a transaction +// is committed to the database. If the callback returns true the transaction +// is committed, otherwise it is rolled back. +type CommitHookCallback func() bool + +// RegisterCommitHook registers a callback that is called whenever a transaction +// is committed to the database. If a callback is already registered, it is replaced. +// If hook is nil, the callback is removed. +func (db *DB) RegisterCommitHook(hook CommitHookCallback) error { + var cb func() int + if hook != nil { + cb = func() int { + stats.Add(numCommitHooks, 1) + if hook() { + return 0 + } + return 1 + } + } + f := func(driverConn any) error { + conn := driverConn.(*sqlite3.SQLiteConn) + conn.RegisterCommitHook(cb) + return nil + } + conn, err := db.rwDB.Conn(context.Background()) if err != nil { return err diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rqlite-8.36.16/db/db_commit_hook_test.go new/rqlite-8.36.18/db/db_commit_hook_test.go --- old/rqlite-8.36.16/db/db_commit_hook_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/rqlite-8.36.18/db/db_commit_hook_test.go 2025-04-19 14:35:27.000000000 +0200 @@ -0,0 +1,105 @@ +package db + +import ( + "os" + "sync/atomic" + "testing" +) + +func Test_CommitHook(t *testing.T) { + path := mustTempPath() + defer os.Remove(path) + db, err := Open(path, false, false) + if err != nil { + t.Fatalf("error opening database") + } + defer db.Close() + mustExecute(db, "CREATE TABLE foo (id INTEGER PRIMARY KEY, name TEXT)") + + count := &atomic.Int32{} + hook := func() bool { + count.Add(1) + return true + } + if err := db.RegisterCommitHook(hook); err != nil { + t.Fatalf("error registering commit hook") + } + + // A select should not trigger the hook and a basic insert should trigger the hook. + mustQuery(db, "SELECT * FROM foo") + mustExecute(db, "INSERT INTO foo(name) VALUES('fiona')") + if count.Load() != 1 { + t.Fatalf("expected count 1, got %d", count.Load()) + } +} + +// Test_CommitHook_Rollback demonstrates that the Commit hook is not called for a +// transaction which is rolled back. +func Test_CommitHook_Rollback(t *testing.T) { + path := mustTempPath() + defer os.Remove(path) + db, err := Open(path, false, false) + if err != nil { + t.Fatalf("error opening database") + } + defer db.Close() + mustExecute(db, "CREATE TABLE foo (id INTEGER PRIMARY KEY, name TEXT)") + + count := &atomic.Int32{} + hook := func() bool { + count.Add(1) + return false + } + if err := db.RegisterCommitHook(hook); err != nil { + t.Fatalf("error registering commit hook") + } + + r, err := db.ExecuteStringStmt(`INSERT INTO foo(name) VALUES("fiona")`) + if err != nil { + t.Fatalf("error executing statement: %s", err.Error()) + } + if r[0].GetError() == "" { + t.Fatal("expected error in response body due to rollback, got nil") + } + if count.Load() != 1 { + t.Fatalf("expected count 1, got %d", count.Load()) + } + + // Query the count in the table, should be zero. + q, err := db.QueryStringStmt("SELECT COUNT(*) FROM foo") + if err != nil { + t.Fatalf("failed to query empty table: %s", err.Error()) + } + if exp, got := `[{"columns":["COUNT(*)"],"types":["integer"],"values":[[0]]}]`, asJSON(q); exp != got { + t.Fatalf("unexpected results for query, expected %s, got %s", exp, got) + } +} + +// Test_CommitHook_Tx demonstrates that the Commit hook is not called for a +// transaction which is rolled back. +func Test_CommitHook_Tx(t *testing.T) { + path := mustTempPath() + defer os.Remove(path) + db, err := Open(path, false, false) + if err != nil { + t.Fatalf("error opening database") + } + defer db.Close() + mustExecute(db, "CREATE TABLE foo (id INTEGER PRIMARY KEY, name TEXT)") + + count := &atomic.Int32{} + hook := func() bool { + count.Add(1) + return true + } + if err := db.RegisterCommitHook(hook); err != nil { + t.Fatalf("error registering commit hook") + } + mustExecute(db, "BEGIN") + mustExecute(db, "INSERT INTO foo(id, name) VALUES(1, 'fiona')") + mustExecute(db, "ROLLBACK") + + if count.Load() != 0 { + t.Fatalf("expected count 0, got %d", count.Load()) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rqlite-8.36.16/db/db_preupdate_test.go new/rqlite-8.36.18/db/db_preupdate_test.go --- old/rqlite-8.36.16/db/db_preupdate_test.go 2025-04-03 19:35:09.000000000 +0200 +++ new/rqlite-8.36.18/db/db_preupdate_test.go 2025-04-19 14:35:27.000000000 +0200 @@ -414,7 +414,7 @@ } // Test_Preupdate_Tx demostrates that the preupdate hook is called for -// transactions which is rolled back. +// a transaction which is rolled back. func Test_Preupdate_Tx(t *testing.T) { path := mustTempPath() defer os.Remove(path) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rqlite-8.36.16/db/db_update_hook_test.go new/rqlite-8.36.18/db/db_update_hook_test.go --- old/rqlite-8.36.16/db/db_update_hook_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/rqlite-8.36.18/db/db_update_hook_test.go 2025-04-19 14:35:27.000000000 +0200 @@ -0,0 +1,116 @@ +package db + +import ( + "os" + "sync" + "sync/atomic" + "testing" + + command "github.com/rqlite/rqlite/v8/command/proto" +) + +// Test_UpdateHook_Basic tests the basic functionality of the update hook, ensuring +// it is triggered for inserts, updates, and deletes, and not triggered for selects, +// executes that don't change anything, and when unregistered. +func Test_UpdateHook_Basic(t *testing.T) { + path := mustTempPath() + defer os.Remove(path) + db, err := Open(path, false, false) + if err != nil { + t.Fatalf("error opening database") + } + defer db.Close() + mustExecute(db, "CREATE TABLE foo (id INTEGER PRIMARY KEY, name TEXT)") + + count := &atomic.Int32{} + hook := func(ev *command.UpdateHookEvent) error { + count.Add(1) + return nil + } + if err := db.RegisterUpdateHook(hook); err != nil { + t.Fatalf("error registering update hook") + } + + // A select should not trigger the hook and a basic insert should trigger the hook. + mustQuery(db, "SELECT * FROM foo") + mustExecute(db, "INSERT INTO foo(name) VALUES('fiona')") + if count.Load() != 1 { + t.Fatalf("expected count 1, got %d", count.Load()) + } + + // An update should trigger the hook, and an update that doesn't change anything + // should not trigger the hook. + mustExecute(db, "UPDATE foo SET name='fiona2' WHERE id=5") + mustExecute(db, "UPDATE foo SET name='fiona2' WHERE id=1") + if count.Load() != 2 { + t.Fatalf("expected count 2, got %d", count.Load()) + } + + // A delete should trigger the hook. + mustExecute(db, "DELETE FROM foo WHERE id=1") + if count.Load() != 3 { + t.Fatalf("expected count 3, got %d", count.Load()) + } + + // Insert 5 rows, make sure the hook is triggered 5 times. + for i := 0; i < 5; i++ { + mustExecute(db, "INSERT INTO foo(name) VALUES('fiona')") + } + if count.Load() != 8 { + t.Fatalf("expected count 8, got %d", count.Load()) + } + + // Delete all rows, make sure the hook is triggered 5 times. + // To work around the TRUNCATE optimization, we delete all rows + // using a WHERE clause. + r := mustQuery(db, "SELECT COUNT(*) FROM foo") + if exp, got := int64(5), r[0].Values[0].Parameters[0].GetI(); exp != got { + t.Fatalf("expected count %d, got %d", exp, got) + } + mustExecute(db, "DELETE FROM foo WHERE id>0") + if count.Load() != 13 { + t.Fatalf("expected count 13, got %d", count.Load()) + } + + // Create table shouldn't trigger the hook. + mustExecute(db, "CREATE TABLE bar (id INTEGER PRIMARY KEY, name TEXT)") + if count.Load() != 13 { + t.Fatalf("expected count 13, got %d", count.Load()) + } + + // Unregister the hook, insert a row, and make sure the hook is not triggered. + if err := db.RegisterUpdateHook(nil); err != nil { + t.Fatalf("error unregistering preupdate hook") + } + mustExecute(db, "INSERT INTO foo(name) VALUES('fiona')") + if count.Load() != 13 { + t.Fatalf("expected count 8, got %d", count.Load()) + } +} + +// Test_UpdateHook_Tx demostrates that the Update hook is called for a +// transaction which is rolled back. +func Test_UpdateHook_Tx(t *testing.T) { + path := mustTempPath() + defer os.Remove(path) + db, err := Open(path, false, false) + if err != nil { + t.Fatalf("error opening database") + } + defer db.Close() + mustExecute(db, "CREATE TABLE foo (id INTEGER PRIMARY KEY, name TEXT)") + + var wg sync.WaitGroup + hook := func(got *command.UpdateHookEvent) error { + defer wg.Done() + return nil + } + if err := db.RegisterUpdateHook(hook); err != nil { + t.Fatalf("error registering update hook") + } + wg.Add(1) + mustExecute(db, "BEGIN") + mustExecute(db, "INSERT INTO foo(id, name) VALUES(1, 'fiona')") + mustExecute(db, "ROLLBACK") + wg.Wait() +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rqlite-8.36.16/go.mod new/rqlite-8.36.18/go.mod --- old/rqlite-8.36.16/go.mod 2025-04-03 19:35:09.000000000 +0200 +++ new/rqlite-8.36.18/go.mod 2025-04-19 14:35:27.000000000 +0200 @@ -7,20 +7,20 @@ require ( github.com/Bowery/prompt v0.0.0-20190916142128-fa8279994f75 github.com/aws/aws-sdk-go-v2 v1.36.3 - github.com/aws/aws-sdk-go-v2/config v1.29.12 - github.com/aws/aws-sdk-go-v2/credentials v1.17.65 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.69 - github.com/aws/aws-sdk-go-v2/service/s3 v1.78.2 + github.com/aws/aws-sdk-go-v2/config v1.29.14 + github.com/aws/aws-sdk-go-v2/credentials v1.17.67 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.72 + github.com/aws/aws-sdk-go-v2/service/s3 v1.79.2 github.com/hashicorp/go-hclog v1.6.3 github.com/hashicorp/raft v1.7.3 github.com/mkideal/cli v0.2.7 github.com/mkideal/pkg v0.1.3 - github.com/rqlite/go-sqlite3 v1.37.0 + github.com/rqlite/go-sqlite3 v1.38.0 github.com/rqlite/raft-boltdb/v2 v2.0.0-20230523104317-c08e70f4de48 github.com/rqlite/rqlite-disco-clients v0.0.0-20250205044118-8ada2b350099 github.com/rqlite/sql v0.0.0-20241111133259-a4122fabb196 go.etcd.io/bbolt v1.4.0 - golang.org/x/net v0.38.0 + golang.org/x/net v0.39.0 google.golang.org/protobuf v1.36.6 ) @@ -36,9 +36,9 @@ github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.25.2 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect github.com/aws/smithy-go v1.22.3 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect @@ -67,14 +67,14 @@ go.etcd.io/etcd/client/v3 v3.5.21 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.36.0 // indirect - golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/term v0.30.0 // indirect - golang.org/x/text v0.23.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect - google.golang.org/grpc v1.71.0 // indirect + golang.org/x/crypto v0.37.0 // indirect + golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect + golang.org/x/sys v0.32.0 // indirect + golang.org/x/term v0.31.0 // indirect + golang.org/x/text v0.24.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect + google.golang.org/grpc v1.71.1 // indirect ) replace ( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rqlite-8.36.16/go.sum new/rqlite-8.36.18/go.sum --- old/rqlite-8.36.16/go.sum 2025-04-03 19:35:09.000000000 +0200 +++ new/rqlite-8.36.18/go.sum 2025-04-19 14:35:27.000000000 +0200 @@ -11,14 +11,14 @@ github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10/go.mod h1:qqvMj6gHLR/EXWZw4ZbqlPbQUyenf4h82UQUlKc+l14= -github.com/aws/aws-sdk-go-v2/config v1.29.12 h1:Y/2a+jLPrPbHpFkpAAYkVEtJmxORlXoo5k2g1fa2sUo= -github.com/aws/aws-sdk-go-v2/config v1.29.12/go.mod h1:xse1YTjmORlb/6fhkWi8qJh3cvZi4JoVNhc+NbJt4kI= -github.com/aws/aws-sdk-go-v2/credentials v1.17.65 h1:q+nV2yYegofO/SUXruT+pn4KxkxmaQ++1B/QedcKBFM= -github.com/aws/aws-sdk-go-v2/credentials v1.17.65/go.mod h1:4zyjAuGOdikpNYiSGpsGz8hLGmUzlY8pc8r9QQ/RXYQ= +github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM= +github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g= +github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.69 h1:6VFPH/Zi9xYFMJKPQOX5URYkQoXRWeJ7V/7Y6ZDYoms= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.69/go.mod h1:GJj8mmO6YT6EqgduWocwhMoxTLFitkhIrK+owzrYL2I= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.72 h1:PcKMOZfp+kNtJTw2HF2op6SjDvwPBYRvz0Y24PQLUR4= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.72/go.mod h1:vq7/m7dahFXcdzWVOvvjasDI9RcsD3RsTfHmDundJYg= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0= @@ -35,14 +35,14 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 h1:moLQUoVq91LiqT1nbvzDukyqAlCv89ZmwaHw/ZFlFZg= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15/go.mod h1:ZH34PJUc8ApjBIfgQCFvkWcUDBtl/WTD+uiYHjd8igA= -github.com/aws/aws-sdk-go-v2/service/s3 v1.78.2 h1:jIiopHEV22b4yQP2q36Y0OmwLbsxNWdWwfZRR5QRRO4= -github.com/aws/aws-sdk-go-v2/service/s3 v1.78.2/go.mod h1:U5SNqwhXB3Xe6F47kXvWihPl/ilGaEDe8HD/50Z9wxc= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.2 h1:pdgODsAhGo4dvzC3JAG5Ce0PX8kWXrTZGx+jxADD+5E= -github.com/aws/aws-sdk-go-v2/service/sso v1.25.2/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0 h1:90uX0veLKcdHVfvxhkWUQSCi5VabtwMLFutYiRke4oo= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 h1:PZV5W8yk4OtH1JAuhV2PXwwO9v5G5Aoj+eMCn4T+1Kc= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.17/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= +github.com/aws/aws-sdk-go-v2/service/s3 v1.79.2 h1:tWUG+4wZqdMl/znThEk9tcCy8tTMxq8dW0JTgamohrY= +github.com/aws/aws-sdk-go-v2/service/s3 v1.79.2/go.mod h1:U5SNqwhXB3Xe6F47kXvWihPl/ilGaEDe8HD/50Z9wxc= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k= github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -227,8 +227,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/rqlite/go-sqlite3 v1.37.0 h1:7lA+Uitgo31OndqdgmSfplinZ+L+CAdsilLItjmYeW4= -github.com/rqlite/go-sqlite3 v1.37.0/go.mod h1:R9H7CatgYBt3c+fSV/5yo2vLh4ZjCB0aMHdkv69fP4A= +github.com/rqlite/go-sqlite3 v1.38.0 h1:o3qTaVEHRzPsvTabUpPGPyNqnCyxEW3ccxHuPeUW/YI= +github.com/rqlite/go-sqlite3 v1.38.0/go.mod h1:R9H7CatgYBt3c+fSV/5yo2vLh4ZjCB0aMHdkv69fP4A= github.com/rqlite/raft-boltdb/v2 v2.0.0-20230523104317-c08e70f4de48 h1:NZ62M+kT0JqhyFUMc8I4SMmfmD4NGJxhb2ePJQXjryc= github.com/rqlite/raft-boltdb/v2 v2.0.0-20230523104317-c08e70f4de48/go.mod h1:CRnsxgy5G8fAf5J+AM0yrsSdxXHKkIYOaq2sm+Q4DYc= github.com/rqlite/rqlite-disco-clients v0.0.0-20250205044118-8ada2b350099 h1:5cqkVLdl6sGJSY3kiF2dqaA3bD+8OS5FUdZqO0BxXLU= @@ -289,10 +289,10 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= +golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= +golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= +golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -311,8 +311,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -321,8 +321,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -350,13 +350,13 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= +golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -364,19 +364,19 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= -golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= +golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 h1:hE3bRWtU6uceqlh4fhrSnUyjKHMKB9KrTLLG+bc0ddM= -google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= -google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e h1:UdXH7Kzbj+Vzastr5nVfccbmFsmYNygVLSPk1pEfDoY= +google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e/go.mod h1:085qFyf2+XaZlRdCgKNCIZ3afY2p4HHZdoIRpId8F4A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e h1:ztQaXfzEXTmCBvbtWYRhJxW+0iJcz2qXfd38/e9l7bA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= +google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= ++++++ vendor.tar.xz ++++++ ++++ 28608 lines of diff (skipped)