@@ -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
)
@@ -184,49 +186,60 @@ func (c *readWriteCursor) Seek(seek []byte) ([]byte, []byte) {
184
186
}
185
187
186
188
// Delete removes the current key/value pair the cursor is at without
187
- // invalidating the cursor. Returns ErrIncompatibleValue if attempted
188
- // when the cursor points to a nested bucket.
189
+ // invalidating the cursor. Returns ErrIncompatibleValue if attempted when the
190
+ // cursor points to a nested bucket.
189
191
func (c * readWriteCursor ) Delete () error {
190
- // Get first record at or after cursor.
191
- var key []byte
192
- row , cancel := c .bucket .tx .QueryRow (
193
- "SELECT key FROM " + c .bucket .table + " WHERE " +
194
- parentSelector (c .bucket .id )+
195
- " AND key>=$1 ORDER BY key LIMIT 1" ,
196
- c .currKey ,
197
- )
198
- defer cancel ()
199
- err := row .Scan (& key )
200
-
201
- switch {
202
- case err == sql .ErrNoRows :
203
- return nil
204
-
205
- case err != nil :
206
- panic (err )
192
+ if c .currKey == nil {
193
+ // Cursor might not be positioned on a valid key.
194
+ return errors .New ("cursor not positioned on a key" )
207
195
}
208
196
209
- // Delete record.
197
+ // Attempt to delete the key the cursor is pointing at, but only if it's
198
+ // a value.
210
199
result , err := c .bucket .tx .Exec (
211
200
"DELETE FROM " + c .bucket .table + " WHERE " +
212
201
parentSelector (c .bucket .id )+
213
202
" AND key=$1 AND value IS NOT NULL" ,
214
- key ,
203
+ c . currKey ,
215
204
)
216
205
if err != nil {
217
206
panic (err )
218
207
}
219
208
220
209
rows , err := result .RowsAffected ()
221
210
if err != nil {
222
- return err
211
+ return fmt .Errorf ("error getting rows affected " +
212
+ "for cursor key %x: %w" , c .currKey , err )
213
+ }
214
+
215
+ // If deletion succeeded, we are done.
216
+ if rows == 1 {
217
+ return nil
223
218
}
224
219
225
- // The key exists but nothing has been deleted. This means that the key
226
- // must have been a bucket key.
227
- if rows != 1 {
220
+ // If rows == 0, the key either didn't exist anymore (concurrent
221
+ // delete?) or it was a bucket. Check if it's a bucket.
222
+ var existsAsBucket int
223
+ rowCheck , cancelCheck := c .bucket .tx .QueryRow (
224
+ "SELECT 1 FROM " + c .bucket .table + " WHERE " +
225
+ parentSelector (c .bucket .id )+
226
+ " AND key=$1 AND value IS NULL" , c .currKey ,
227
+ )
228
+ defer cancelCheck ()
229
+
230
+ errCheck := rowCheck .Scan (& existsAsBucket )
231
+ if errCheck == nil {
232
+ // Found it, and value IS NULL -> It's a bucket.
228
233
return walletdb .ErrIncompatibleValue
229
234
}
230
235
231
- return err
236
+ if errCheck == sql .ErrNoRows {
237
+ return nil
238
+ }
239
+
240
+ // Some other error during the check.
241
+ //
242
+ // TODO(roasbeef): panic here like above/
243
+ return fmt .Errorf ("error checking if cursor key %x is " +
244
+ "bucket: %w" , c .currKey , errCheck )
232
245
}
0 commit comments