or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-transforms.mdcli.mdcore-language.mdindex.mdjson.mdsql.mdswing.mdtemplates.mdxml.md

sql.mddocs/

0

# Database Access

1

2

Groovy provides comprehensive database access through the Sql class and DataSet, offering simplified JDBC operations, connection management, and result processing with Groovy's dynamic features.

3

4

## Database Connections

5

6

### Sql

7

8

Main class for database operations providing simplified JDBC access.

9

10

```groovy { .api }

11

class Sql implements Closeable {

12

// Factory methods for creating connections

13

static Sql newInstance(String url)

14

static Sql newInstance(String url, Properties properties)

15

static Sql newInstance(String url, String user, String password)

16

static Sql newInstance(String url, String user, String password, String driverClassName)

17

static Sql newInstance(String url, String user, String password, Properties properties, String driverClassName)

18

static Sql newInstance(Map<String, Object> args)

19

static Sql newInstance(DataSource dataSource)

20

static Sql newInstance(Connection connection)

21

22

// Query methods

23

List<GroovyRowResult> rows(String sql)

24

List<GroovyRowResult> rows(String sql, List<Object> params)

25

List<GroovyRowResult> rows(String sql, Map params)

26

List<GroovyRowResult> rows(String sql, Object... params)

27

List<GroovyRowResult> rows(Map params, String sql)

28

29

GroovyRowResult firstRow(String sql)

30

GroovyRowResult firstRow(String sql, List<Object> params)

31

GroovyRowResult firstRow(String sql, Map params)

32

GroovyRowResult firstRow(String sql, Object... params)

33

34

void eachRow(String sql, Closure closure)

35

void eachRow(String sql, List<Object> params, Closure closure)

36

void eachRow(String sql, Map params, Closure closure)

37

void eachRow(String sql, int offset, int maxRows, Closure closure)

38

void eachRow(String sql, List<Object> params, int offset, int maxRows, Closure closure)

39

40

// Update methods

41

int executeUpdate(String sql)

42

int executeUpdate(String sql, List<Object> params)

43

int executeUpdate(String sql, Map params)

44

int executeUpdate(String sql, Object... params)

45

46

boolean execute(String sql)

47

boolean execute(String sql, List<Object> params)

48

boolean execute(String sql, Map params)

49

List<List<Object>> executeInsert(String sql)

50

List<List<Object>> executeInsert(String sql, List<Object> params)

51

52

// Prepared statement support

53

void withStatement(Closure closure)

54

Object call(String sql, List<Object> params, Closure closure)

55

Object call(String sql, Closure closure)

56

57

// Transaction support

58

void withTransaction(Closure closure)

59

void commit()

60

void rollback()

61

void setAutoCommit(boolean autoCommit)

62

boolean getAutoCommit()

63

64

// Batch operations

65

void withBatch(String sql, Closure closure)

66

void withBatch(int batchSize, String sql, Closure closure)

67

int[] executeBatch(String sql)

68

69

// Connection management

70

Connection getConnection()

71

DataSource getDataSource()

72

void close()

73

boolean isClosed()

74

}

75

```

76

77

Usage examples:

78

```groovy

79

import groovy.sql.Sql

80

81

// Create connection

82

def sql = Sql.newInstance(

83

'jdbc:h2:mem:testdb',

84

'sa',

85

'',

86

'org.h2.Driver'

87

)

88

89

// Create table

90

sql.execute '''

91

CREATE TABLE person (

92

id INTEGER PRIMARY KEY,

93

name VARCHAR(50),

94

age INTEGER,

95

email VARCHAR(100)

96

)

97

'''

98

99

// Insert data

100

sql.executeUpdate '''

101

INSERT INTO person (id, name, age, email)

102

VALUES (?, ?, ?, ?)

103

''', [1, 'John Doe', 30, 'john@example.com']

104

105

// Insert with named parameters

106

sql.executeUpdate '''

107

INSERT INTO person (id, name, age, email)

108

VALUES (:id, :name, :age, :email)

109

''', [id: 2, name: 'Jane Smith', age: 25, email: 'jane@example.com']

110

111

// Query all rows

112

def people = sql.rows('SELECT * FROM person ORDER BY name')

113

people.each { person ->

114

println "${person.name} (${person.age})"

115

}

116

117

// Query with parameters

118

def adults = sql.rows('SELECT * FROM person WHERE age >= ?', [21])

119

def john = sql.firstRow('SELECT * FROM person WHERE name = ?', ['John Doe'])

120

121

// Iterate through results

122

sql.eachRow('SELECT * FROM person') { row ->

123

println "ID: ${row.id}, Name: ${row.name}, Email: ${row.email}"

124

}

125

126

// Update records

127

def updated = sql.executeUpdate(

128

'UPDATE person SET age = ? WHERE name = ?',

129

[31, 'John Doe']

130

)

131

println "Updated $updated records"

132

133

// Close connection

134

sql.close()

135

```

136

137

### GroovyRowResult

138

139

Enhanced result row that provides map-like and object-like access to column values.

140

141

```groovy { .api }

142

class GroovyRowResult implements Map<String, Object> {

143

Object getAt(int index)

144

Object getAt(String columnName)

145

void putAt(String columnName, Object value)

146

void putAt(int index, Object value)

147

148

Object getProperty(String property)

149

void setProperty(String property, Object value)

150

151

// Map interface methods

152

int size()

153

boolean isEmpty()

154

boolean containsKey(Object key)

155

boolean containsValue(Object value)

156

Object get(Object key)

157

Object put(String key, Object value)

158

Object remove(Object key)

159

void putAll(Map<? extends String, ?> m)

160

void clear()

161

Set<String> keySet()

162

Collection<Object> values()

163

Set<Map.Entry<String, Object>> entrySet()

164

165

// Utility methods

166

String toString()

167

}

168

```

169

170

Usage example:

171

```groovy

172

def person = sql.firstRow('SELECT * FROM person WHERE id = ?', [1])

173

174

// Access columns by name

175

assert person.name == 'John Doe'

176

assert person['email'] == 'john@example.com'

177

178

// Access columns by index

179

assert person[1] == 'John Doe' // Assuming name is second column

180

181

// Use as Map

182

person.each { key, value ->

183

println "$key: $value"

184

}

185

186

// Modify values (for update operations)

187

person.age = 32

188

sql.executeUpdate(

189

'UPDATE person SET age = ? WHERE id = ?',

190

[person.age, person.id]

191

)

192

```

193

194

## Dataset Operations

195

196

### DataSet

197

198

Higher-level abstraction for table operations with automatic SQL generation.

199

200

```groovy { .api }

201

class DataSet {

202

DataSet(Sql sql, String table)

203

DataSet(DataSet parent, String table)

204

DataSet(DataSet parent, Closure where)

205

206

// Query operations

207

void each(Closure closure)

208

void eachWithIndex(Closure closure)

209

List findAll(Closure where)

210

Object find(Closure where)

211

GroovyRowResult firstRow()

212

List<GroovyRowResult> rows()

213

int size()

214

215

// Data modification

216

void add(Map<String, Object> values)

217

DataSet findAll(Closure where)

218

int update(Map<String, Object> values)

219

int update(Closure where, Map<String, Object> values)

220

221

// Dataset operations

222

DataSet createView(Closure where)

223

DataSet reverse()

224

DataSet sort(Closure sort)

225

226

String getTable()

227

Sql getSql()

228

}

229

```

230

231

Usage examples:

232

```groovy

233

import groovy.sql.DataSet

234

235

def personTable = sql.dataSet('person')

236

237

// Add records

238

personTable.add(name: 'Alice Brown', age: 28, email: 'alice@example.com')

239

personTable.add(name: 'Bob Wilson', age: 35, email: 'bob@example.com')

240

241

// Query with closures

242

def adults = personTable.findAll { it.age >= 21 }

243

def alice = personTable.find { it.name == 'Alice Brown' }

244

245

// Iterate through records

246

personTable.each { person ->

247

println "${person.name}: ${person.email}"

248

}

249

250

// Update records

251

personTable.update(age: 29) { it.name == 'Alice Brown' }

252

253

// Create filtered views

254

def seniors = personTable.createView { it.age >= 65 }

255

def youngAdults = personTable.createView { it.age >= 18 && it.age < 30 }

256

257

// Sort data

258

def sortedByAge = personTable.sort { it.age }

259

def sortedByName = personTable.sort { it.name }

260

```

261

262

## Stored Procedures

263

264

### Parameter Types

265

266

Support for stored procedure input, output, and input/output parameters.

267

268

```groovy { .api }

269

class OutParameter {

270

OutParameter(int sqlType)

271

OutParameter(int sqlType, int scale)

272

OutParameter(int sqlType, String typeName)

273

274

int getType()

275

int getScale()

276

String getTypeName()

277

}

278

279

class InOutParameter extends OutParameter {

280

InOutParameter(Object value, int sqlType)

281

InOutParameter(Object value, int sqlType, int scale)

282

InOutParameter(Object value, int sqlType, String typeName)

283

284

Object getValue()

285

}

286

287

class ResultSetOutParameter extends OutParameter {

288

ResultSetOutParameter(int sqlType)

289

}

290

```

291

292

Usage examples:

293

```groovy

294

import groovy.sql.OutParameter

295

import groovy.sql.InOutParameter

296

import java.sql.Types

297

298

// Call stored procedure with output parameters

299

def outParam = new OutParameter(Types.VARCHAR)

300

def inOutParam = new InOutParameter('initial', Types.VARCHAR)

301

302

def result = sql.call(

303

'{call GetPersonInfo(?, ?, ?)}',

304

[1, outParam, inOutParam]

305

)

306

307

println "Output parameter: ${result[1]}"

308

println "InOut parameter: ${result[2]}"

309

310

// Call function that returns result set

311

def resultSetParam = new ResultSetOutParameter(Types.REF_CURSOR)

312

sql.call('{? = call GetAllPersons()}', [resultSetParam]) { cursor ->

313

cursor.eachRow { row ->

314

println "${row.name}: ${row.email}"

315

}

316

}

317

```

318

319

## Transaction Management

320

321

### Transaction Control

322

323

```groovy

324

// Automatic transaction management

325

sql.withTransaction { connection ->

326

sql.executeUpdate('UPDATE person SET age = age + 1 WHERE id = ?', [1])

327

sql.executeUpdate('INSERT INTO audit_log (action, timestamp) VALUES (?, ?)',

328

['age_increment', new Date()])

329

// Transaction automatically committed on success, rolled back on exception

330

}

331

332

// Manual transaction control

333

try {

334

sql.autoCommit = false

335

336

sql.executeUpdate('DELETE FROM person WHERE age < ?', [18])

337

def deletedCount = sql.updateCount

338

339

if (deletedCount > 10) {

340

throw new RuntimeException('Too many records would be deleted')

341

}

342

343

sql.commit()

344

println "Successfully deleted $deletedCount records"

345

346

} catch (Exception e) {

347

sql.rollback()

348

println "Transaction rolled back: ${e.message}"

349

} finally {

350

sql.autoCommit = true

351

}

352

```

353

354

## Batch Operations

355

356

### Batch Processing

357

358

```groovy

359

// Simple batch execution

360

def batchData = [

361

[3, 'Charlie Brown', 22, 'charlie@example.com'],

362

[4, 'Diana Prince', 27, 'diana@example.com'],

363

[5, 'Edward Norton', 35, 'edward@example.com']

364

]

365

366

sql.withBatch('INSERT INTO person (id, name, age, email) VALUES (?, ?, ?, ?)') { stmt ->

367

batchData.each { person ->

368

stmt.addBatch(person)

369

}

370

}

371

372

// Batch with size limit

373

sql.withBatch(100, 'INSERT INTO large_table (data) VALUES (?)') { stmt ->

374

(1..1000).each { i ->

375

stmt.addBatch(["Data item $i"])

376

}

377

}

378

379

// Manual batch control

380

def stmt = sql.connection.prepareStatement('UPDATE person SET last_login = ? WHERE id = ?')

381

try {

382

[1, 2, 3, 4, 5].each { id ->

383

stmt.setTimestamp(1, new java.sql.Timestamp(System.currentTimeMillis()))

384

stmt.setInt(2, id)

385

stmt.addBatch()

386

}

387

int[] results = stmt.executeBatch()

388

println "Batch update results: $results"

389

} finally {

390

stmt.close()

391

}

392

```

393

394

## Connection Pooling

395

396

### DataSource Integration

397

398

```groovy

399

import org.apache.commons.dbcp2.BasicDataSource

400

401

// Create connection pool

402

def dataSource = new BasicDataSource()

403

dataSource.driverClassName = 'org.h2.Driver'

404

dataSource.url = 'jdbc:h2:mem:testdb'

405

dataSource.username = 'sa'

406

dataSource.password = ''

407

dataSource.initialSize = 5

408

dataSource.maxTotal = 20

409

410

// Use with Groovy SQL

411

def sql = new Sql(dataSource)

412

413

// Perform operations

414

sql.eachRow('SELECT * FROM person') { row ->

415

println row.name

416

}

417

418

// Connection automatically returned to pool when Sql instance is closed

419

sql.close()

420

421

// Shutdown pool when application ends

422

dataSource.close()

423

```

424

425

## Error Handling

426

427

### Exception Handling

428

429

```groovy

430

import java.sql.SQLException

431

import java.sql.SQLIntegrityConstraintViolationException

432

433

try {

434

sql.executeUpdate('INSERT INTO person (id, name) VALUES (?, ?)', [1, 'Duplicate'])

435

} catch (SQLIntegrityConstraintViolationException e) {

436

println "Constraint violation: ${e.message}"

437

} catch (SQLException e) {

438

println "SQL error (${e.SQLState}): ${e.message}"

439

} catch (Exception e) {

440

println "General error: ${e.message}"

441

}

442

443

// Check for warnings

444

def warnings = sql.connection.warnings

445

while (warnings) {

446

println "Warning: ${warnings.message}"

447

warnings = warnings.nextWarning

448

}

449

```

450

451

## Advanced Features

452

453

### Metadata Access

454

455

```groovy

456

// Database metadata

457

def metaData = sql.connection.metaData

458

println "Database: ${metaData.databaseProductName} ${metaData.databaseProductVersion}"

459

println "Driver: ${metaData.driverName} ${metaData.driverVersion}"

460

461

// Table information

462

def tables = sql.rows("""

463

SELECT table_name, table_type

464

FROM information_schema.tables

465

WHERE table_schema = 'PUBLIC'

466

""")

467

468

tables.each { table ->

469

println "Table: ${table.table_name} (${table.table_type})"

470

}

471

472

// Column information

473

def columns = sql.rows("""

474

SELECT column_name, data_type, is_nullable

475

FROM information_schema.columns

476

WHERE table_name = 'PERSON'

477

""")

478

479

columns.each { col ->

480

println "Column: ${col.column_name} - ${col.data_type} (nullable: ${col.is_nullable})"

481

}

482

```

483

484

### Custom Type Handling

485

486

```groovy

487

import java.sql.Types

488

489

// Custom type conversion

490

sql.resultSetConcurrency = java.sql.ResultSet.CONCUR_UPDATABLE

491

492

// Handle special data types

493

sql.eachRow('SELECT id, data, created_date FROM special_table') { row ->

494

def id = row.id

495

def jsonData = row.data // Assuming CLOB containing JSON

496

def timestamp = row.created_date

497

498

// Process custom types

499

if (jsonData) {

500

def parsed = new groovy.json.JsonSlurper().parseText(jsonData.toString())

501

println "JSON data: $parsed"

502

}

503

}

504

505

// Insert custom types

506

def jsonData = groovy.json.JsonOutput.toJson([key: 'value', number: 42])

507

sql.executeUpdate(

508

'INSERT INTO special_table (data, created_date) VALUES (?, ?)',

509

[jsonData, new java.sql.Timestamp(System.currentTimeMillis())]

510

)

511

```