@@ -4,6 +4,8 @@ package sqlbase
4
4
5
5
import (
6
6
"database/sql"
7
+ "errors"
8
+ "fmt"
7
9
8
10
"github.com/btcsuite/btcwallet/walletdb"
9
11
)
@@ -230,3 +232,62 @@ func (c *readWriteCursor) Delete() error {
230
232
231
233
return err
232
234
}
235
+
236
+ // Delete removes the current key/value pair the cursor is at without
237
+ // invalidating the cursor. Returns ErrIncompatibleValue if attempted when the
238
+ // cursor points to a nested bucket.
239
+ func (c * readWriteCursor ) Delete () error {
240
+ if c .currKey == nil {
241
+ // Cursor might not be positioned on a valid key.
242
+ return errors .New ("cursor not positioned on a key" )
243
+ }
244
+
245
+ // Attempt to delete the key the cursor is pointing at, but only if it's
246
+ // a value.
247
+ result , err := c .bucket .tx .Exec (
248
+ "DELETE FROM " + c .bucket .table + " WHERE " +
249
+ parentSelector (c .bucket .id )+
250
+ " AND key=$1 AND value IS NOT NULL" ,
251
+ c .currKey ,
252
+ )
253
+ if err != nil {
254
+ panic (err )
255
+ }
256
+
257
+ rows , err := result .RowsAffected ()
258
+ if err != nil {
259
+ return fmt .Errorf ("error getting rows affected " +
260
+ "for cursor key %x: %w" , c .currKey , err )
261
+ }
262
+
263
+ // If deletion succeeded, we are done.
264
+ if rows == 1 {
265
+ return nil
266
+ }
267
+
268
+ // If rows == 0, the key either didn't exist anymore (concurrent
269
+ // delete?) or it was a bucket. Check if it's a bucket.
270
+ var existsAsBucket int
271
+ rowCheck , cancelCheck := c .bucket .tx .QueryRow (
272
+ "SELECT 1 FROM " + c .bucket .table + " WHERE " +
273
+ parentSelector (c .bucket .id )+
274
+ " AND key=$1 AND value IS NULL" , c .currKey ,
275
+ )
276
+ defer cancelCheck ()
277
+
278
+ errCheck := rowCheck .Scan (& existsAsBucket )
279
+ if errCheck == nil {
280
+ // Found it, and value IS NULL -> It's a bucket.
281
+ return walletdb .ErrIncompatibleValue
282
+ }
283
+
284
+ if errCheck == sql .ErrNoRows {
285
+ return nil
286
+ }
287
+
288
+ // Some other error during the check.
289
+ //
290
+ // TODO(roasbeef): panic here like above/
291
+ return fmt .Errorf ("error checking if cursor key %x is " +
292
+ "bucket: %w" , c .currKey , errCheck )
293
+ }
0 commit comments