or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcluster-management.mdconnection-management.mddbapi-interface.mdexception-handling.mdindex.mdquery-execution.mdtransaction-management.mdtype-system.md

query-execution.mddocs/

0

# Query Execution

1

2

Prepared statement interface with parameter binding, result streaming, and transaction management for efficient and secure database operations.

3

4

## Capabilities

5

6

### Statement Preparation

7

8

Create prepared statements for efficient repeated execution with automatic parameter binding and type conversion.

9

10

```python { .api }

11

def prepare(statement):

12

"""

13

Create a prepared statement from SQL with parameter placeholders.

14

15

Parameters:

16

- statement (str): SQL statement with $1, $2, etc. parameter placeholders

17

18

Returns:

19

Statement: Prepared statement object for repeated execution

20

21

Raises:

22

QueryError: If statement cannot be prepared

23

"""

24

```

25

26

### Statement Interface

27

28

Prepared statement object providing multiple execution modes for different use cases.

29

30

```python { .api }

31

class Statement:

32

"""

33

Prepared statement with parameter binding and multiple execution modes.

34

"""

35

36

def __call__(*parameters):

37

"""

38

Execute statement and return all results.

39

40

Parameters:

41

- *parameters: Values for statement parameters ($1, $2, etc.)

42

43

Returns:

44

List of result rows or command result

45

46

Raises:

47

QueryError: If execution fails

48

"""

49

50

def first(*parameters):

51

"""

52

Execute statement and return first result row.

53

54

Parameters:

55

- *parameters: Values for statement parameters

56

57

Returns:

58

Row or None: First result row or None if no results

59

"""

60

61

def rows(*parameters):

62

"""

63

Execute statement and return iterator over result rows.

64

65

Parameters:

66

- *parameters: Values for statement parameters

67

68

Returns:

69

Iterator[Row]: Iterator over result rows for streaming

70

"""

71

72

def chunks(*parameters):

73

"""

74

Execute statement and return chunked results.

75

76

Parameters:

77

- *parameters: Values for statement parameters

78

79

Returns:

80

Chunks: Chunked result iterator for large datasets

81

"""

82

83

def column(*parameters):

84

"""

85

Execute statement and return iterator over single column values.

86

87

Parameters:

88

- *parameters: Values for statement parameters

89

90

Returns:

91

Iterator: Iterator over values from the first column

92

"""

93

94

def declare(*parameters):

95

"""

96

Create a scrollable cursor for the statement.

97

98

Parameters:

99

- *parameters: Values for statement parameters

100

101

Returns:

102

Cursor: Scrollable cursor for navigation and fetching

103

"""

104

105

def close():

106

"""Close the prepared statement."""

107

108

@property

109

def sql():

110

"""

111

Get the SQL text of the prepared statement.

112

113

Returns:

114

str: Original SQL statement text

115

"""

116

117

@property

118

def parameter_types():

119

"""

120

Get parameter type information.

121

122

Returns:

123

List[int]: PostgreSQL type OIDs for parameters

124

"""

125

126

@property

127

def result_types():

128

"""

129

Get result column type information.

130

131

Returns:

132

List[int]: PostgreSQL type OIDs for result columns

133

"""

134

```

135

136

### Direct Query Execution

137

138

Execute queries directly without preparation for one-time operations.

139

140

```python { .api }

141

def execute(statement, *parameters):

142

"""

143

Execute a statement directly with parameters.

144

145

Parameters:

146

- statement (str): SQL statement

147

- *parameters: Parameter values

148

149

Returns:

150

Command result or row data

151

"""

152

153

def query(statement, *parameters):

154

"""

155

Execute a query and return all results.

156

157

Parameters:

158

- statement (str): SQL query

159

- *parameters: Parameter values

160

161

Returns:

162

List[Row]: All result rows

163

"""

164

```

165

166

### Result Row Interface

167

168

Result rows providing both positional and named access to column values.

169

170

```python { .api }

171

class Row:

172

"""

173

Result row with named and positional access to column values.

174

"""

175

176

def __getitem__(key):

177

"""

178

Get column value by index or name.

179

180

Parameters:

181

- key (int or str): Column index or name

182

183

Returns:

184

Column value with automatic type conversion

185

"""

186

187

def __len__():

188

"""

189

Get number of columns in row.

190

191

Returns:

192

int: Number of columns

193

"""

194

195

def keys():

196

"""

197

Get column names.

198

199

Returns:

200

List[str]: Column names

201

"""

202

203

def values():

204

"""

205

Get column values.

206

207

Returns:

208

List: Column values

209

"""

210

211

def items():

212

"""

213

Get column name-value pairs.

214

215

Returns:

216

List[tuple]: (name, value) pairs

217

"""

218

```

219

220

### Chunked Results

221

222

Interface for processing large result sets in chunks to manage memory usage.

223

224

```python { .api }

225

class Chunks:

226

"""

227

Chunked result iterator for processing large datasets efficiently.

228

"""

229

230

def __iter__():

231

"""

232

Iterate over result chunks.

233

234

Returns:

235

Iterator[List[Row]]: Iterator over chunks of rows

236

"""

237

238

def __next__():

239

"""

240

Get next chunk of results.

241

242

Returns:

243

List[Row]: Next chunk of rows

244

245

Raises:

246

StopIteration: When no more chunks available

247

"""

248

249

def close():

250

"""Close the chunked result iterator."""

251

```

252

253

### Cursor Interface

254

255

Scrollable cursor for bidirectional navigation through result sets with seek operations.

256

257

```python { .api }

258

class Cursor:

259

"""

260

Scrollable cursor providing bidirectional navigation through query results.

261

"""

262

263

def read(quantity=None, direction=None):

264

"""

265

Read rows from the cursor position.

266

267

Parameters:

268

- quantity (int, optional): Number of rows to read (default: all remaining)

269

- direction (str, optional): 'FORWARD' or 'BACKWARD' (default: cursor direction)

270

271

Returns:

272

List[Row]: List of rows read from cursor

273

"""

274

275

def seek(offset, whence='ABSOLUTE'):

276

"""

277

Move cursor to specified position.

278

279

Parameters:

280

- offset (int): Position offset

281

- whence (str): 'ABSOLUTE', 'RELATIVE', 'FORWARD', or 'BACKWARD'

282

"""

283

284

def __next__():

285

"""

286

Get next row from cursor.

287

288

Returns:

289

Row: Next row in cursor direction

290

291

Raises:

292

StopIteration: When no more rows available

293

"""

294

295

def clone():

296

"""

297

Create a copy of the cursor.

298

299

Returns:

300

Cursor: New cursor instance at same position

301

"""

302

303

def close():

304

"""Close the cursor and release resources."""

305

306

@property

307

def direction():

308

"""

309

Get cursor direction.

310

311

Returns:

312

bool: True for FORWARD, False for BACKWARD

313

"""

314

315

@property

316

def cursor_id():

317

"""

318

Get cursor identifier.

319

320

Returns:

321

str: Unique cursor identifier

322

"""

323

324

@property

325

def column_names():

326

"""

327

Get result column names.

328

329

Returns:

330

List[str]: Column names in result order

331

"""

332

333

@property

334

def column_types():

335

"""

336

Get result column types.

337

338

Returns:

339

List[type]: Python types for result columns

340

"""

341

342

@property

343

def statement():

344

"""

345

Get associated statement.

346

347

Returns:

348

Statement: The statement that created this cursor

349

"""

350

```

351

352

## Usage Examples

353

354

### Basic Statement Preparation and Execution

355

356

```python

357

import postgresql

358

359

db = postgresql.open('pq://user:pass@localhost/mydb')

360

361

# Prepare statement for repeated use

362

get_user = db.prepare("SELECT id, name, email FROM users WHERE id = $1")

363

364

# Execute with parameter

365

user = get_user.first(123)

366

if user:

367

print(f"User: {user['name']} ({user['email']})")

368

369

# Execute multiple times efficiently

370

user_ids = [1, 2, 3, 4, 5]

371

for user_id in user_ids:

372

user = get_user.first(user_id)

373

if user:

374

print(f"ID {user_id}: {user['name']}")

375

376

get_user.close()

377

```

378

379

### Streaming Large Result Sets

380

381

```python

382

import postgresql

383

384

db = postgresql.open('pq://user:pass@localhost/mydb')

385

386

# Prepare query for large dataset

387

get_all_orders = db.prepare("""

388

SELECT order_id, customer_id, order_date, total

389

FROM orders

390

WHERE order_date >= $1

391

ORDER BY order_date

392

""")

393

394

# Stream results to avoid loading all into memory

395

from datetime import date

396

start_date = date(2023, 1, 1)

397

398

total_amount = 0

399

order_count = 0

400

401

for order in get_all_orders.rows(start_date):

402

total_amount += order['total']

403

order_count += 1

404

405

# Process order

406

print(f"Order {order['order_id']}: ${order['total']}")

407

408

print(f"Processed {order_count} orders, total: ${total_amount}")

409

```

410

411

### Chunked Processing

412

413

```python

414

import postgresql

415

416

db = postgresql.open('pq://user:pass@localhost/mydb')

417

418

# Process large dataset in chunks

419

get_transactions = db.prepare("SELECT * FROM transactions WHERE processed = false")

420

421

# Process in chunks of 1000 rows

422

for chunk in get_transactions.chunks():

423

batch_updates = []

424

425

for transaction in chunk:

426

# Process transaction

427

result = process_transaction(transaction)

428

batch_updates.append((result, transaction['id']))

429

430

# Batch update processed transactions

431

update_stmt = db.prepare("UPDATE transactions SET result = $1, processed = true WHERE id = $2")

432

for result, tx_id in batch_updates:

433

update_stmt(result, tx_id)

434

435

print(f"Processed chunk of {len(chunk)} transactions")

436

```

437

438

### Parameter Types and Query Building

439

440

```python

441

import postgresql

442

443

db = postgresql.open('pq://user:pass@localhost/mydb')

444

445

# Prepare statement with multiple parameter types

446

search_query = db.prepare("""

447

SELECT product_id, name, price, in_stock

448

FROM products

449

WHERE category = $1

450

AND price BETWEEN $2 AND $3

451

AND in_stock = $4

452

ORDER BY price

453

""")

454

455

# Execute with different parameter types

456

products = search_query(

457

"electronics", # str

458

100.0, # float

459

500.0, # float

460

True # bool

461

)

462

463

for product in products:

464

stock_status = "In Stock" if product['in_stock'] else "Out of Stock"

465

print(f"{product['name']}: ${product['price']} - {stock_status}")

466

467

# Check statement metadata

468

print(f"Parameter types: {search_query.parameter_types}")

469

print(f"Result types: {search_query.result_types}")

470

```

471

472

### Direct Query Execution

473

474

```python

475

import postgresql

476

477

db = postgresql.open('pq://user:pass@localhost/mydb')

478

479

# One-time queries don't need preparation

480

table_count = db.query("SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public'")[0][0]

481

print(f"Public tables: {table_count}")

482

483

# Execute DDL or commands

484

db.execute("CREATE INDEX IF NOT EXISTS idx_user_email ON users(email)")

485

db.execute("ANALYZE users")

486

487

# Execute with parameters

488

recent_users = db.query(

489

"SELECT name FROM users WHERE created_at > $1",

490

datetime.now() - timedelta(days=7)

491

)

492

493

for user in recent_users:

494

print(f"Recent user: {user['name']}")

495

```

496

497

### Error Handling

498

499

```python

500

import postgresql

501

import postgresql.exceptions as pg_exc

502

503

db = postgresql.open('pq://user:pass@localhost/mydb')

504

505

try:

506

# Prepare potentially problematic statement

507

stmt = db.prepare("SELECT * FROM maybe_missing_table WHERE id = $1")

508

result = stmt.first(123)

509

510

except pg_exc.ProgrammingError as e:

511

print(f"SQL error: {e}")

512

# Handle missing table, invalid SQL, etc.

513

514

except pg_exc.DataError as e:

515

print(f"Data error: {e}")

516

# Handle invalid parameter values, type conversion errors

517

518

except pg_exc.ConnectionError as e:

519

print(f"Connection error: {e}")

520

# Handle connection issues

521

522

finally:

523

if 'stmt' in locals():

524

stmt.close()

525

```