@@ -174,3 +174,135 @@ func Test_Changeset_OneRow(t *testing.T) {
174174 t .Fatalf ("Failed to finalize changeset iterator: %v" , err )
175175 }
176176}
177+
178+ func Test_Changeset_Multi (t * testing.T ) {
179+ db , err := sql .Open ("sqlite3" , ":memory:" )
180+ if err != nil {
181+ t .Fatal ("Failed to open" , err )
182+ }
183+ err = db .Ping ()
184+ if err != nil {
185+ t .Fatal ("Failed to ping" , err )
186+ }
187+ defer db .Close ()
188+
189+ ctx := context .Background ()
190+ conn , err := db .Conn (ctx )
191+ if err != nil {
192+ t .Fatal ("Failed to get connection to database:" , err )
193+ }
194+ defer conn .Close ()
195+
196+ // Create tables, and attach a session.
197+ mustExecute (conn , `CREATE TABLE table1 (id INTEGER PRIMARY KEY, name TEXT, gpa FLOAT, alive boolean)` )
198+ mustExecute (conn , `CREATE TABLE table2 (id INTEGER PRIMARY KEY, age INTEGER)` )
199+ var session * Session
200+ if err := conn .Raw (func (raw any ) error {
201+ var err error
202+ session , err = raw .(* SQLiteConn ).CreateSession ("main" )
203+ return err
204+ }); err != nil {
205+ t .Fatal ("Failed to create session:" , err )
206+ }
207+ defer func () {
208+ if err := session .DeleteSession (); err != nil {
209+ t .Fatalf ("Failed to delete session: %v" , err )
210+ }
211+ }()
212+ err = session .AttachSession ("" )
213+ if err != nil {
214+ t .Fatalf ("Failed to attach session to table: %v" , err )
215+ }
216+
217+ // Make a bunch of changes.
218+ mustExecute (conn , `INSERT INTO table1 (name, gpa, alive) VALUES ('fiona', 3.5, 1)` )
219+ mustExecute (conn , `INSERT INTO table1 (name, gpa, alive) VALUES ('declan', 2.5, 0)` )
220+ mustExecute (conn , `INSERT INTO table2 (age) VALUES (20)` )
221+ mustExecute (conn , `INSERT INTO table2 (age) VALUES (30)` )
222+
223+ // Prepare to iterate over the changes.
224+ changeset , err := NewChangeset (session )
225+ if err != nil {
226+ t .Fatalf ("Failed to generate changeset: %v" , err )
227+ }
228+ iter , err := NewChangesetIterator (changeset )
229+ if err != nil {
230+ t .Fatalf ("Failed to create changeset iterator: %v" , err )
231+ }
232+
233+ tt := []struct {
234+ table string
235+ op int
236+ data []any
237+ }{
238+ {
239+ table : "table1" ,
240+ op : SQLITE_INSERT ,
241+ data : []any {int64 (1 ), "fiona" , 3.5 , int64 (1 )},
242+ },
243+ {
244+ table : "table1" ,
245+ op : SQLITE_INSERT ,
246+ data : []any {int64 (2 ), "declan" , 2.5 , int64 (0 )},
247+ },
248+ {
249+ table : "table2" ,
250+ op : SQLITE_INSERT ,
251+ data : []any {int64 (1 ), int64 (20 )},
252+ },
253+ {
254+ table : "table2" ,
255+ op : SQLITE_INSERT ,
256+ data : []any {int64 (2 ), int64 (30 )},
257+ },
258+ }
259+
260+ for _ , v := range tt {
261+ if b , err := iter .Next (); err != nil {
262+ t .Fatalf ("Failed to get next changeset: %v" , err )
263+ } else if ! b {
264+ t .Fatalf ("changeset does not contain changes: %v" , b )
265+ }
266+
267+ tblName , nCol , op , _ , err := iter .Op ()
268+ if err != nil {
269+ t .Fatalf ("Failed to get changeset operation: %v" , err )
270+ }
271+ if exp , got := v .table , tblName ; exp != got {
272+ t .Fatalf ("Expected table name '%s', got '%s'" , exp , got )
273+ }
274+ if exp , got := len (v .data ), nCol ; exp != got {
275+ t .Fatalf ("Expected %d columns, got %d" , exp , got )
276+ }
277+ if exp , got := v .op , op ; exp != got {
278+ t .Fatalf ("Expected operation %d, got %d" , exp , got )
279+ }
280+
281+ dest := make ([]any , nCol )
282+ if err := iter .New (dest ); err != nil {
283+ t .Fatalf ("Failed to get new row: %v" , err )
284+ }
285+ for j , d := range v .data {
286+ if exp , got := d , dest [j ]; exp != got {
287+ t .Fatalf ("Expected %v (%T) for dest[%d], got %v (%T)" , exp , exp , j , got , got )
288+ }
289+ }
290+ }
291+
292+ if b , err := iter .Next (); err != nil {
293+ t .Fatalf ("Failed to get next changeset: %v" , err )
294+ } else if b {
295+ t .Fatalf ("changeset contains changes: %v" , b )
296+ }
297+
298+ if err := iter .Finalize (); err != nil {
299+ t .Fatalf ("Failed to finalize changeset iterator: %v" , err )
300+ }
301+ }
302+
303+ func mustExecute (conn * sql.Conn , stmt string ) {
304+ _ , err := conn .ExecContext (context .Background (), stmt )
305+ if err != nil {
306+ panic (err )
307+ }
308+ }
0 commit comments