CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-codehaus-groovy--groovy-sql

A facade over Java's JDBC APIs providing greatly simplified resource management and result set handling with Groovy-specific enhancements.

Pending
Overview
Eval results
Files

result-handling.mddocs/

Result Handling

Groovy SQL provides specialized result handling classes that offer Groovy-friendly access to database results. These classes bridge the gap between JDBC's ResultSet interface and Groovy's expressive syntax patterns.

GroovyRowResult

GroovyRowResult is a Map-like wrapper for SQL result rows that provides case-insensitive column access and integrates seamlessly with Groovy's property access syntax.

Constructor

GroovyRowResult(Map<String, Object> result)

Property Access

Access column values using Groovy property syntax with case-insensitive column names:

Object getProperty(String property)

Index Access

Access columns by their position in the result set:

Object getAt(int index)  // Supports negative indices for reverse access

Map Interface

GroovyRowResult implements the full Map interface with case-insensitive key handling:

// Map interface methods
void clear()
boolean containsKey(Object key)  // Case-insensitive
boolean containsValue(Object value)
Set<Map.Entry<String, Object>> entrySet()
boolean equals(Object o)
Object get(Object property)  // Case-insensitive
int hashCode()
boolean isEmpty()
Set<String> keySet()
Object put(String key, Object value)  // Handles case-insensitive replacement
void putAll(Map<? extends String, ?> t)
Object remove(Object rawKey)  // Case-insensitive
int size()
Collection<Object> values()

GroovyResultSet

GroovyResultSet extends the standard JDBC ResultSet interface with Groovy-specific enhancements for more expressive data access patterns.

Interface Definition

interface GroovyResultSet extends ResultSet, GroovyObject

Enhanced Column Access

Access columns using Groovy's array-like syntax:

Object getAt(int index)  // Supports negative indices
Object getAt(String columnName)  // Case-insensitive column access

Column Updates

Update column values using Groovy's assignment syntax:

void putAt(int index, Object newValue)
void putAt(String columnName, Object newValue)

Row Operations

Add new rows and iterate using closures:

void add(Map values)  // Add new row from map
void eachRow(Closure closure)  // Iterate with closure

GroovyResultSetExtension

Implementation class that provides the actual functionality for GroovyResultSet:

Constructor

GroovyResultSetExtension(ResultSet set)

Property Access

Object getProperty(String columnName)
void setProperty(String columnName, Object newValue)

Index Access

Object getAt(int index)  // Supports negative indices
void putAt(int index, Object newValue)

Navigation

boolean next()
boolean previous()

Row Operations

void add(Map values)
void eachRow(Closure closure)

Method Delegation

Object invokeMethod(String name, Object args)  // Delegates to underlying ResultSet

GroovyResultSetProxy

Proxy class for creating GroovyResultSet instances:

Constructors

GroovyResultSetProxy(ResultSet set)
GroovyResultSetProxy(GroovyResultSetExtension ext)

Proxy Methods

GroovyResultSet getImpl()  // Get proxy instance
Object invoke(Object proxy, Method method, Object[] args)  // InvocationHandler method

ResultSetMetaDataWrapper

Wrapper for accessing ResultSetMetaData columns with Groovy syntax:

Constructor

ResultSetMetaDataWrapper(ResultSetMetaData target, int index)

Metadata Access

Object invokeMethod(String name, Object args)  // Invoke metadata methods with column index
Object getProperty(String property)  // Get metadata properties for column
void setProperty(String property, Object newValue)  // Read-only (throws exception)

Usage Examples

GroovyRowResult Access Patterns

def sql = Sql.newInstance("jdbc:h2:mem:test", "sa", "", "org.h2.Driver")

// Different ways to access column values
sql.eachRow("SELECT user_id, first_name, last_name, email FROM users") { row ->
    // Property access (case-insensitive)
    println "User ID: ${row.user_id}"
    println "Name: ${row.first_name} ${row.last_name}"
    
    // Alternative case variations work
    println "Email: ${row.EMAIL}"  // Works even if column is lowercase
    println "Name: ${row.First_Name}"  // Works with different casing
    
    // Index access
    println "First column: ${row[0]}"  // user_id
    println "Last column: ${row[-1]}"  // email (negative index)
    
    // Map-style access
    println "User: ${row.get('first_name')}"
    println "Contains email: ${row.containsKey('email')}"
}

GroovyResultSet Operations

def sql = Sql.newInstance("jdbc:h2:mem:test", "sa", "", "org.h2.Driver")

// Using GroovyResultSet in query closure
sql.query("SELECT * FROM users WHERE active = ?", [true]) { rs ->
    while (rs.next()) {
        // Groovy-style column access
        def userName = rs['user_name']
        def userEmail = rs['email']
        
        // Update values
        rs['last_login'] = new Date()
        
        // Access by index (supports negative)
        def firstCol = rs[0]  // First column
        def lastCol = rs[-1]  // Last column
        
        println "User: ${userName}, Email: ${userEmail}"
    }
}

Case-Insensitive Column Access

def sql = Sql.newInstance("jdbc:h2:mem:test", "sa", "", "org.h2.Driver")

sql.eachRow("SELECT USER_NAME, USER_EMAIL, CREATED_DATE FROM users") { row ->
    // All these work regardless of actual column case
    println row.user_name     // Works
    println row.USER_NAME     // Works  
    println row.User_Name     // Works
    println row.userName      // Works
    
    // Map access is also case-insensitive
    println row['user_email']   // Works
    println row['USER_EMAIL']   // Works
    println row['userEmail']    // Works
}

Working with Complex Data Types

def sql = Sql.newInstance("jdbc:h2:mem:test", "sa", "", "org.h2.Driver")

sql.eachRow("SELECT id, data, created_at FROM complex_table") { row ->
    // Handle different data types
    def id = row.id as Integer
    def jsonData = row.data as String
    def timestamp = row.created_at as Timestamp
    
    // Check for null values
    if (row.data != null) {
        println "Data: ${jsonData}"
    }
    
    // Convert to appropriate types
    def date = timestamp?.toLocalDateTime()
    println "Created: ${date}"
}

Metadata Access

def sql = Sql.newInstance("jdbc:h2:mem:test", "sa", "", "org.h2.Driver")

sql.eachRow("SELECT * FROM users", { meta ->
    // Access metadata using wrapper
    def columnCount = meta.columnCount
    println "Result has ${columnCount} columns:"
    
    (1..columnCount).each { i ->
        def column = meta[i-1]  // 0-based index
        println "Column ${i}: ${column.columnName} (${column.columnTypeName})"
    }
}) { row ->
    // Process rows
    println "Row: ${row}"
}

Row Manipulation

def sql = Sql.newInstance("jdbc:h2:mem:test", "sa", "", "org.h2.Driver")

// Collect results with transformations
def results = []
sql.eachRow("SELECT name, age, salary FROM employees") { row ->
    // Create modified result
    def employee = [:]
    employee.name = row.name?.toUpperCase()
    employee.age = row.age as Integer
    employee.salaryCategory = row.salary > 50000 ? 'high' : 'standard'
    
    results << employee
}

results.each { emp ->
    println "${emp.name}: ${emp.salaryCategory} salary"
}

Integration with Groovy Collections

def sql = Sql.newInstance("jdbc:h2:mem:test", "sa", "", "org.h2.Driver")

// Get all rows and use Groovy collection methods
def users = sql.rows("SELECT name, age, department FROM users")

// Filter using Groovy methods
def youngUsers = users.findAll { it.age < 30 }
def departments = users.collect { it.department }.unique()
def avgAge = users.sum { it.age } / users.size()

println "Young users: ${youngUsers.size()}"
println "Departments: ${departments}"
println "Average age: ${avgAge}"

// Group by department
def byDept = users.groupBy { it.department }
byDept.each { dept, empList ->
    println "${dept}: ${empList.size()} employees"
}

Install with Tessl CLI

npx tessl i tessl/maven-org-codehaus-groovy--groovy-sql

docs

batch-transactions.md

core-operations.md

dataset-operations.md

index.md

parameters-procedures.md

result-handling.md

tile.json