or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cursors.mddatabase-management.mdindex.mdjson-collections.mdjx9-scripting.mdkey-value.mdtransactions.mdutilities.md

cursors.mddocs/

0

# Cursor Operations

1

2

Efficient database traversal and iteration capabilities for large datasets with positioning and filtering support. Cursors provide low-level access for manual record traversal and bulk operations.

3

4

## Capabilities

5

6

### Cursor Creation and Management

7

8

Create and manage database cursors for efficient traversal.

9

10

```python { .api }

11

def cursor(self):

12

"""Create a cursor for iterating through the database.

13

Returns Cursor object."""

14

...

15

16

class Cursor:

17

def __enter__(self):

18

"""Enter context manager. Resets cursor position."""

19

...

20

21

def __exit__(self, exc_type, exc_val, exc_tb):

22

"""Exit context manager."""

23

...

24

```

25

26

**Usage Example:**

27

28

```python

29

db = unqlite.UnQLite(':mem:')

30

31

# Add test data

32

for i in range(10):

33

db[f'key{i:02d}'] = f'value{i}'

34

35

# Create and use cursor

36

cursor = db.cursor()

37

38

# Use as context manager for automatic cleanup

39

with db.cursor() as cursor:

40

cursor.first()

41

while cursor.is_valid():

42

key = cursor.key()

43

value = cursor.value()

44

print(f"{key}: {value}")

45

try:

46

cursor.next_entry()

47

except StopIteration:

48

break

49

```

50

51

### Cursor Positioning

52

53

Move cursor to specific positions within the database.

54

55

```python { .api }

56

def reset(self):

57

"""Reset the cursor's position."""

58

...

59

60

def seek(self, key, flags=UNQLITE_CURSOR_MATCH_EXACT):

61

"""Seek to the given key using specified matching flags."""

62

...

63

64

def first(self):

65

"""Set cursor to the first record in the database."""

66

...

67

68

def last(self):

69

"""Set cursor to the last record in the database."""

70

...

71

```

72

73

**Usage Example:**

74

75

```python

76

db = unqlite.UnQLite(':mem:')

77

78

# Add sorted test data

79

keys = ['apple', 'banana', 'cherry', 'date', 'elderberry']

80

for key in keys:

81

db[key] = f'fruit:{key}'

82

83

with db.cursor() as cursor:

84

# Move to first record

85

cursor.first()

86

print(f"First: {cursor.key()} = {cursor.value()}")

87

88

# Move to last record

89

cursor.last()

90

print(f"Last: {cursor.key()} = {cursor.value()}")

91

92

# Seek to specific key

93

cursor.seek('cherry')

94

print(f"Found: {cursor.key()} = {cursor.value()}")

95

96

# Seek with different matching modes

97

cursor.seek('c', flags=unqlite.UNQLITE_CURSOR_MATCH_GE) # Greater or equal

98

print(f"First key >= 'c': {cursor.key()}")

99

```

100

101

### Cursor Movement

102

103

Navigate between records sequentially.

104

105

```python { .api }

106

def next_entry(self):

107

"""Move cursor to the next entry. Raises StopIteration at end."""

108

...

109

110

def previous_entry(self):

111

"""Move cursor to the previous entry. Raises StopIteration at beginning."""

112

...

113

114

def is_valid(self):

115

"""Return True if cursor points to a valid record."""

116

...

117

```

118

119

**Usage Example:**

120

121

```python

122

db = unqlite.UnQLite(':mem:')

123

124

# Add test data

125

for i in range(5):

126

db[f'item{i}'] = f'data{i}'

127

128

with db.cursor() as cursor:

129

# Forward iteration

130

cursor.first()

131

print("Forward iteration:")

132

while cursor.is_valid():

133

print(f" {cursor.key()}: {cursor.value()}")

134

try:

135

cursor.next_entry()

136

except StopIteration:

137

break

138

139

# Backward iteration

140

cursor.last()

141

print("Backward iteration:")

142

while cursor.is_valid():

143

print(f" {cursor.key()}: {cursor.value()}")

144

try:

145

cursor.previous_entry()

146

except StopIteration:

147

break

148

```

149

150

### Data Access

151

152

Access key and value data at cursor's current position.

153

154

```python { .api }

155

def key(self):

156

"""Retrieve the key at the cursor's current location."""

157

...

158

159

def value(self):

160

"""Retrieve the value at the cursor's current location."""

161

...

162

163

def delete(self):

164

"""Delete the record at the cursor's current location."""

165

...

166

```

167

168

**Usage Example:**

169

170

```python

171

db = unqlite.UnQLite(':mem:')

172

173

# Add test data with different types

174

db['string_key'] = 'text_value'

175

db['json_key'] = '{"type": "json", "valid": true}'

176

db['binary_key'] = b'\x00\x01\x02\x03'

177

178

with db.cursor() as cursor:

179

cursor.first()

180

while cursor.is_valid():

181

key = cursor.key()

182

value = cursor.value()

183

184

print(f"Key: {key} (type: {type(key)})")

185

print(f"Value: {value} (type: {type(value)})")

186

187

# Delete specific records

188

if key == 'binary_key':

189

cursor.delete()

190

print("Deleted binary record")

191

else:

192

try:

193

cursor.next_entry()

194

except StopIteration:

195

break

196

```

197

198

### Iterator Interface

199

200

Use cursors as Python iterators for convenient traversal.

201

202

```python { .api }

203

def __iter__(self):

204

"""Return iterator for cursor."""

205

...

206

207

def __next__(self):

208

"""Get next key-value pair. Raises StopIteration at end."""

209

...

210

211

def fetch_until(self, stop_key, include_stop_key=True):

212

"""Iterate until specified key is reached."""

213

...

214

```

215

216

**Usage Example:**

217

218

```python

219

db = unqlite.UnQLite(':mem:')

220

221

# Add range of data

222

for i in range(20):

223

db[f'record{i:03d}'] = f'data_{i}'

224

225

# Iterate using cursor as iterator

226

with db.cursor() as cursor:

227

print("All records:")

228

for key, value in cursor:

229

print(f" {key}: {value}")

230

231

# Partial iteration with fetch_until

232

with db.cursor() as cursor:

233

cursor.seek('record005')

234

print("Records from record005 to record010:")

235

for key, value in cursor.fetch_until('record010'):

236

print(f" {key}: {value}")

237

```

238

239

## Database-Level Iteration Methods

240

241

UnQLite provides convenient iteration methods that use cursors internally.

242

243

```python { .api }

244

def keys(self):

245

"""Efficiently iterate through the database's keys."""

246

...

247

248

def values(self):

249

"""Efficiently iterate through the database's values."""

250

...

251

252

def items(self):

253

"""Efficiently iterate through the database's key-value pairs."""

254

...

255

256

def range(self, start_key, end_key, include_end_key=True):

257

"""Iterate over a range of keys."""

258

...

259

260

def __iter__(self):

261

"""Return iterator for database keys."""

262

...

263

```

264

265

**Usage Example:**

266

267

```python

268

db = unqlite.UnQLite(':mem:')

269

270

# Add test data

271

data = {'alpha': '1', 'beta': '2', 'gamma': '3', 'delta': '4'}

272

db.update(data)

273

274

# Iterate over keys only

275

print("Keys:")

276

for key in db.keys():

277

print(f" {key}")

278

279

# Iterate over values only

280

print("Values:")

281

for value in db.values():

282

print(f" {value}")

283

284

# Iterate over key-value pairs

285

print("Items:")

286

for key, value in db.items():

287

print(f" {key}: {value}")

288

289

# Range iteration

290

print("Range from 'beta' to 'gamma':")

291

for key, value in db.range('beta', 'gamma'):

292

print(f" {key}: {value}")

293

294

# Database as iterator (keys only)

295

print("Database iteration:")

296

for key in db:

297

print(f" {key}: {db[key]}")

298

```

299

300

## Cursor Seek Modes

301

302

Control how the cursor positions itself when seeking to keys.

303

304

```python

305

# Exact match (default)

306

unqlite.UNQLITE_CURSOR_MATCH_EXACT

307

308

# Less than or equal to key

309

unqlite.UNQLITE_CURSOR_MATCH_LE

310

311

# Greater than or equal to key

312

unqlite.UNQLITE_CURSOR_MATCH_GE

313

```

314

315

**Usage Example:**

316

317

```python

318

db = unqlite.UnQLite(':mem:')

319

320

# Add sorted data

321

keys = ['aardvark', 'bear', 'cat', 'dog', 'elephant']

322

for key in keys:

323

db[key] = f'animal:{key}'

324

325

with db.cursor() as cursor:

326

# Find exact match

327

try:

328

cursor.seek('cat', unqlite.UNQLITE_CURSOR_MATCH_EXACT)

329

print(f"Exact match: {cursor.key()}")

330

except:

331

print("Exact match not found")

332

333

# Find first key >= 'cow' (will find 'dog')

334

cursor.seek('cow', unqlite.UNQLITE_CURSOR_MATCH_GE)

335

print(f"First key >= 'cow': {cursor.key()}")

336

337

# Find last key <= 'cow' (will find 'cat')

338

cursor.seek('cow', unqlite.UNQLITE_CURSOR_MATCH_LE)

339

print(f"Last key <= 'cow': {cursor.key()}")

340

```

341

342

## Performance Considerations

343

344

Cursors are highly efficient for:

345

- **Large dataset traversal**: O(1) per record vs O(n) for repeated lookups

346

- **Sequential processing**: Optimal disk/memory access patterns

347

- **Range queries**: Efficient key range iteration

348

- **Bulk operations**: Process many records with minimal overhead

349

350

```python

351

db = unqlite.UnQLite('large.db')

352

353

# Efficient: Use cursor for large dataset processing

354

with db.cursor() as cursor:

355

for key, value in cursor:

356

# Process each record efficiently

357

process_record(key, value)

358

359

# Inefficient: Individual key lookups

360

for key in db.keys(): # This internally uses a cursor

361

value = db[key] # This is an additional lookup

362

process_record(key, value)

363

```

364

365

## Error Handling

366

367

Cursor operations handle various error conditions:

368

369

```python

370

db = unqlite.UnQLite(':mem:')

371

372

with db.cursor() as cursor:

373

try:

374

# Movement operations raise StopIteration at boundaries

375

cursor.first()

376

while True:

377

print(cursor.key())

378

cursor.next_entry() # Will eventually raise StopIteration

379

380

except StopIteration:

381

print("Reached end of database")

382

383

try:

384

# Seek operations may raise exceptions for invalid keys

385

cursor.seek('nonexistent_key')

386

387

except unqlite.UnQLiteError as e:

388

print(f"Seek failed: {e}")

389

```