github.com/RevenueMonster/sqlike@v1.0.6/examples/transaction.go (about) 1 package examples 2 3 import ( 4 "context" 5 "database/sql" 6 "errors" 7 "math/rand" 8 "testing" 9 "time" 10 11 "cloud.google.com/go/civil" 12 uuid "github.com/google/uuid" 13 14 "github.com/RevenueMonster/sqlike/sql/expr" 15 "github.com/RevenueMonster/sqlike/sqlike" 16 "github.com/RevenueMonster/sqlike/sqlike/actions" 17 "github.com/RevenueMonster/sqlike/sqlike/options" 18 "github.com/stretchr/testify/require" 19 ) 20 21 type user struct { 22 ID int `sqlike:"$Key"` 23 Name string 24 } 25 26 // TransactionExamples : 27 func TransactionExamples(ctx context.Context, t *testing.T, db *sqlike.Database) { 28 var ( 29 uid uuid.UUID 30 ns normalStruct 31 result sql.Result 32 affected int64 33 err error 34 tx *sqlike.Transaction 35 ) 36 37 // Commit Transaction 38 { 39 uid, _ = uuid.Parse(`be72fc34-917b-11e9-af91-6c96cfd87a51`) 40 now := time.Now() 41 42 ns = normalStruct{} 43 ns.ID = uid 44 ns.Date = civil.DateOf(now) 45 ns.DateTime = now 46 ns.Timestamp = now 47 ns.CreatedAt = now 48 ns.UpdatedAt = now 49 tx, err = db.BeginTransaction(ctx) 50 require.NoError(t, err) 51 result, err = tx.Table("NormalStruct").InsertOne(ctx, &ns) 52 require.NoError(t, err) 53 affected, err = result.RowsAffected() 54 require.NoError(t, err) 55 require.Equal(t, int64(1), affected) 56 57 err = tx.CommitTransaction() 58 require.NoError(t, err) 59 } 60 61 // Abort Transaction 62 { 63 uid, _ = uuid.Parse(`be7191c8-917b-11e9-af91-6c96cfd87a51`) 64 now := time.Now() 65 66 ns = normalStruct{} 67 ns.ID = uid 68 ns.Date = civil.DateOf(now) 69 ns.DateTime = now 70 ns.Timestamp = now 71 ns.CreatedAt = now 72 ns.UpdatedAt = now 73 tx, err = db.BeginTransaction(ctx) 74 require.NoError(t, err) 75 result, err = tx.Table("NormalStruct").InsertOne(ctx, &ns) 76 require.NoError(t, err) 77 affected, err = result.RowsAffected() 78 require.NoError(t, err) 79 require.Equal(t, int64(1), affected) 80 81 err = tx.RollbackTransaction() 82 require.NoError(t, err) 83 84 ns = normalStruct{} 85 err = db.Table("NormalStruct").FindOne( 86 ctx, 87 actions.FindOne(). 88 Where( 89 expr.Equal("$Key", uid), 90 ), 91 ).Decode(&ns) 92 require.Equal(t, sql.ErrNoRows, err) 93 } 94 95 // RunInTransaction 96 { 97 err = db.RunInTransaction(ctx, 98 func(sess sqlike.SessionContext) error { 99 uid, _ = uuid.Parse(`4ab3898c-9192-11e9-b500-6c96cfd87a51`) 100 now := time.Now() 101 102 ns = normalStruct{} 103 ns.ID = uid 104 ns.Date = civil.DateOf(now) 105 ns.DateTime = now 106 ns.Timestamp = now 107 ns.CreatedAt = now 108 ns.UpdatedAt = now 109 result, err := sess.Table("NormalStruct").InsertOne(sess, &ns) 110 if err != nil { 111 return err 112 } 113 114 ns.Int = 888 115 if _, err := sess.Table("NormalStruct"). 116 UpdateOne( 117 sess, 118 actions.UpdateOne(). 119 Where( 120 expr.Equal("$Key", ns.ID), 121 ). 122 Set( 123 expr.ColumnValue("Int", ns.Int), 124 ), 125 ); err != nil { 126 return err 127 } 128 129 affected, err := result.RowsAffected() 130 if err != nil { 131 return err 132 } 133 if affected < 1 { 134 return errors.New("no result affected") 135 } 136 return nil 137 }) 138 require.NoError(t, err) 139 } 140 141 // Timeout transaction 142 { 143 uid, _ = uuid.Parse(`5eb3f5c6-bfdb-11e9-88c7-6c96cfd87a51`) 144 now := time.Now() 145 err = db.RunInTransaction( 146 ctx, func(sess sqlike.SessionContext) error { 147 ns = normalStruct{} 148 ns.ID = uid 149 ns.Date = civil.DateOf(now) 150 ns.DateTime = now 151 ns.Timestamp = now 152 ns.CreatedAt = now 153 ns.UpdatedAt = now 154 _, err := sess.Table("NormalStruct"). 155 InsertOne( 156 sess, 157 &ns, options.InsertOne().SetDebug(true), 158 ) 159 if err != nil { 160 return err 161 } 162 time.Sleep(5 * time.Second) 163 return nil 164 }, options.Transaction().SetTimeOut(3*time.Second)) 165 require.Equal(t, sql.ErrTxDone, err) 166 167 rslt := normalStruct{} 168 err = db.Table("NormalStruct").FindOne( 169 ctx, 170 actions.FindOne(). 171 Where( 172 expr.Equal("$Key", uid), 173 ), 174 options.FindOne().SetDebug(true), 175 ).Decode(&rslt) 176 require.Error(t, err) 177 require.Equal(t, normalStruct{}, rslt) 178 } 179 180 // Lock record using transaction 181 { 182 err = db.RunInTransaction( 183 ctx, func(sess sqlike.SessionContext) error { 184 nss := []normalStruct{} 185 result, err := sess.Table("NormalStruct"). 186 Find( 187 sess, 188 nil, options.Find(). 189 SetLockMode(options.LockForUpdate). 190 SetDebug(true), 191 ) 192 if err != nil { 193 return err 194 } 195 if err := result.All(&nss); err != nil { 196 return err 197 } 198 time.Sleep(1 * time.Second) 199 return nil 200 }) 201 require.NoError(t, err) 202 } 203 204 err = db.Table("UserAddress").DropIfExists(ctx) 205 require.NoError(t, err) 206 207 table := db.Table("user") 208 err = table.DropIfExists(ctx) 209 require.NoError(t, err) 210 table.MustMigrate(ctx, new(user)) 211 212 // Commit Transaction 213 { 214 data := &user{ID: rand.Intn(10000), Name: "Oska"} 215 trx, _ := db.BeginTransaction(ctx) 216 _, err = trx.Table("user").InsertOne(ctx, data) 217 require.NoError(t, err) 218 219 err = trx.Table("user").FindOne( 220 ctx, 221 actions.FindOne(). 222 Where( 223 expr.Equal("$Key", data.ID), 224 ), 225 ).Decode(&user{}) 226 require.NoError(t, err) 227 228 err = db.Table("user").FindOne( 229 ctx, 230 actions.FindOne(). 231 Where( 232 expr.Equal("$Key", data.ID), 233 ), 234 ).Decode(&user{}) 235 require.Error(t, err) 236 237 err = trx.CommitTransaction() 238 require.NoError(t, err) 239 240 err = db.Table("user").FindOne( 241 ctx, 242 actions.FindOne(). 243 Where( 244 expr.Equal("$Key", data.ID), 245 ), 246 ).Decode(&user{}) 247 require.NoError(t, err) 248 249 // Remove tested data 250 err = db.Table("user").DestroyOne(ctx, data) 251 require.NoError(t, err) 252 } 253 254 // Rollback Transaction 255 { 256 data := &user{ID: 1234, Name: "Oska"} 257 trx, _ := db.BeginTransaction(ctx) 258 _, err = trx.Table("user").InsertOne(ctx, data) 259 require.NoError(t, err) 260 261 err = trx.Table("user").FindOne( 262 ctx, 263 actions.FindOne(). 264 Where( 265 expr.Equal("$Key", data.ID), 266 ), 267 ).Decode(&user{}) 268 require.NoError(t, err) 269 270 err = db.Table("user").FindOne( 271 ctx, 272 actions.FindOne(). 273 Where( 274 expr.Equal("$Key", data.ID), 275 ), 276 ).Decode(&user{}) 277 require.Error(t, err) 278 279 err = trx.RollbackTransaction() 280 require.NoError(t, err) 281 282 err = db.Table("user").FindOne( 283 ctx, 284 actions.FindOne(). 285 Where( 286 expr.Equal("$Key", data.ID), 287 ), 288 ).Decode(&user{}) 289 require.Error(t, err) 290 } 291 }