A facade over Java's JDBC APIs providing greatly simplified resource management and result set handling with Groovy-specific enhancements.
—
Groovy SQL provides a comprehensive type-safe parameter system for stored procedure calls, supporting input, output, and input/output parameters with proper JDBC type mapping and automatic result handling.
Interface for input parameters with type information:
interface InParameter {
int getType() // Get JDBC data type constant
Object getValue() // Get parameter value
}Interface for output parameters from stored procedures:
interface OutParameter {
int getType() // Get JDBC data type constant
}Interface for bidirectional parameters (both input and output):
interface InOutParameter extends InParameter, OutParameter {
// Inherits getType() from both interfaces
// Inherits getValue() from InParameter
}Interface for result set output parameters:
interface ResultSetOutParameter extends OutParameter {
// Inherits getType() from OutParameter
}Interface for variables that should be expanded into SQL rather than parameterized:
interface ExpandedVariable {
Object getObject() // Get the object to expand into SQL
}Create typed input parameters:
static InParameter in(int type, Object value)Create output parameters for stored procedures:
static OutParameter out(int type)Create input/output parameters:
static InOutParameter inout(InParameter in)Create result set output parameters:
static ResultSetOutParameter resultSet(int type)Create variables for SQL expansion:
static ExpandedVariable expand(Object object)Pre-defined output parameter constants for all JDBC types:
static final OutParameter ARRAY
static final OutParameter BIGINT
static final OutParameter BINARY
static final OutParameter BIT
static final OutParameter BLOB
static final OutParameter BOOLEAN
static final OutParameter CHAR
static final OutParameter CLOB
static final OutParameter DATALINK
static final OutParameter DATE
static final OutParameter DECIMAL
static final OutParameter DISTINCT
static final OutParameter DOUBLE
static final OutParameter FLOAT
static final OutParameter INTEGER
static final OutParameter JAVA_OBJECT
static final OutParameter LONGVARBINARY
static final OutParameter LONGVARCHAR
static final OutParameter NULL
static final OutParameter NUMERIC
static final OutParameter OTHER
static final OutParameter REAL
static final OutParameter REF
static final OutParameter SMALLINT
static final OutParameter STRUCT
static final OutParameter TIME
static final OutParameter TIMESTAMP
static final OutParameter TINYINT
static final OutParameter VARBINARY
static final OutParameter VARCHARCreate typed input parameters using convenience methods:
static InParameter ARRAY(Object value)
static InParameter BIGINT(Object value)
static InParameter BINARY(Object value)
static InParameter BIT(Object value)
static InParameter BLOB(Object value)
static InParameter BOOLEAN(Object value)
static InParameter CHAR(Object value)
static InParameter CLOB(Object value)
static InParameter DATALINK(Object value)
static InParameter DATE(Object value)
static InParameter DECIMAL(Object value)
static InParameter DISTINCT(Object value)
static InParameter DOUBLE(Object value)
static InParameter FLOAT(Object value)
static InParameter INTEGER(Object value)
static InParameter JAVA_OBJECT(Object value)
static InParameter LONGVARBINARY(Object value)
static InParameter LONGVARCHAR(Object value)
static InParameter NULL(Object value)
static InParameter NUMERIC(Object value)
static InParameter OTHER(Object value)
static InParameter REAL(Object value)
static InParameter REF(Object value)
static InParameter SMALLINT(Object value)
static InParameter STRUCT(Object value)
static InParameter TIME(Object value)
static InParameter TIMESTAMP(Object value)
static InParameter TINYINT(Object value)
static InParameter VARBINARY(Object value)
static InParameter VARCHAR(Object value)Execute stored procedures and return result codes:
int call(String sql) throws Exception
int call(String sql, List<Object> params) throws Exception
int call(String sql, Object[] params) throws Exception
int call(GString gstring) throws ExceptionExecute procedures and process output parameters:
void call(String sql, List<Object> params, Closure closure) throws Exception
void call(GString gstring, Closure closure) throws ExceptionThe closure receives an Object[] containing all output parameter values.
Execute procedures that return result sets:
List<GroovyRowResult> callWithRows(String sql, List<Object> params, Closure closure) throws SQLException
List<GroovyRowResult> callWithRows(GString gstring, Closure closure) throws SQLExceptionExecute procedures that return multiple result sets:
List<List<GroovyRowResult>> callWithAllRows(String sql, List<Object> params, Closure closure) throws SQLException
List<List<GroovyRowResult>> callWithAllRows(GString gstring, Closure closure) throws SQLExceptionimport groovy.sql.Sql
import static groovy.sql.Sql.*
def sql = Sql.newInstance("jdbc:h2:mem:test", "sa", "", "org.h2.Driver")
// Create typed input parameters
def nameParam = VARCHAR("John Doe")
def ageParam = INTEGER(30)
def salaryParam = DECIMAL(75000.50)
def activeParam = BOOLEAN(true)
// Use in query
sql.execute("INSERT INTO employees (name, age, salary, active) VALUES (?, ?, ?, ?)",
[nameParam, ageParam, salaryParam, activeParam])def sql = Sql.newInstance("jdbc:oracle:thin:@localhost:1521:xe", "user", "pass", "oracle.jdbc.OracleDriver")
// Call procedure with input parameters
def empId = 100
def newSalary = 85000
def result = sql.call("{ call update_salary(?, ?) }", [empId, newSalary])
println "Procedure returned: ${result}"def sql = Sql.newInstance("jdbc:oracle:thin:@localhost:1521:xe", "user", "pass", "oracle.jdbc.OracleDriver")
// Call procedure with input and output parameters
def empId = 100
def params = [
INTEGER(empId), // Input parameter
out(VARCHAR), // Output: employee name
out(DECIMAL), // Output: current salary
out(DATE) // Output: hire date
]
sql.call("{ call get_employee_info(?, ?, ?, ?) }", params) { outParams ->
def employeeName = outParams[0]
def currentSalary = outParams[1]
def hireDate = outParams[2]
println "Employee: ${employeeName}"
println "Salary: \$${currentSalary}"
println "Hired: ${hireDate}"
}def sql = Sql.newInstance("jdbc:sqlserver://localhost:1433;databaseName=test", "user", "pass", "com.microsoft.sqlserver.jdbc.SQLServerDriver")
// Create input parameter that will also receive output
def salaryParam = DECIMAL(75000)
def inOutSalary = inout(salaryParam)
def params = [
INTEGER(100), // Employee ID (input)
DECIMAL(0.10), // Raise percentage (input)
inOutSalary // Current salary (input/output)
]
sql.call("{ call give_raise(?, ?, ?) }", params) { outParams ->
def newSalary = outParams[0] // The updated salary
println "New salary: \$${newSalary}"
}def sql = Sql.newInstance("jdbc:postgresql://localhost:5432/test", "user", "pass", "org.postgresql.Driver")
// Call procedure that returns a result set
def deptId = 10
def employees = sql.callWithRows("{ call get_department_employees(?) }", [INTEGER(deptId)]) { outParams ->
// Process any output parameters if present
if (outParams) {
println "Additional output: ${outParams}"
}
}
employees.each { emp ->
println "Employee: ${emp.name}, Salary: ${emp.salary}"
}def sql = Sql.newInstance("jdbc:sqlserver://localhost:1433;databaseName=test", "user", "pass", "com.microsoft.sqlserver.jdbc.SQLServerDriver")
// Call procedure that returns multiple result sets
def allResults = sql.callWithAllRows("{ call get_company_report() }", []) { outParams ->
if (outParams) {
println "Report generated at: ${outParams[0]}"
}
}
// Process multiple result sets
allResults.eachWithIndex { resultSet, index ->
println "Result Set ${index + 1}:"
resultSet.each { row ->
println " ${row}"
}
}def sql = Sql.newInstance("jdbc:oracle:thin:@localhost:1521:xe", "user", "pass", "oracle.jdbc.OracleDriver")
// Mix of different parameter types
def params = [
VARCHAR("Engineering"), // Department name
out(INTEGER), // Output: department ID
out(DECIMAL), // Output: average salary
out(INTEGER), // Output: employee count
resultSet(OTHER) // Output: result set cursor
]
sql.call("{ call analyze_department(?, ?, ?, ?, ?) }", params) { outParams ->
def deptId = outParams[0]
def avgSalary = outParams[1]
def empCount = outParams[2]
def resultSetCursor = outParams[3]
println "Department ID: ${deptId}"
println "Average Salary: \$${avgSalary}"
println "Employee Count: ${empCount}"
// Process result set if available
if (resultSetCursor instanceof ResultSet) {
while (resultSetCursor.next()) {
println "Detail: ${resultSetCursor.getString(1)}"
}
}
}def sql = Sql.newInstance("jdbc:h2:mem:test", "sa", "", "org.h2.Driver")
def employeeId = 100
def raisePercentage = 0.15
// GString call with parameter
sql.call("{ call give_raise(${INTEGER(employeeId)}, ${DECIMAL(raisePercentage)}, ${out(DECIMAL)}) }") { outParams ->
def newSalary = outParams[0]
println "Employee ${employeeId} new salary: \$${newSalary}"
}def sql = Sql.newInstance("jdbc:h2:mem:test", "sa", "", "org.h2.Driver")
// Use expand() for dynamic SQL parts that shouldn't be parameterized
def tableName = "employees"
def columnName = "salary"
def params = [
expand(tableName), // Will be expanded directly into SQL
expand(columnName), // Will be expanded directly into SQL
DECIMAL(50000) // Will be parameterized normally
]
// This allows dynamic table/column names while still using parameters for values
sql.eachRow("SELECT * FROM ${params[0]} WHERE ${params[1]} > ?", [params[2]]) { row ->
println "Employee: ${row.name}, Salary: ${row.salary}"
}def sql = Sql.newInstance("jdbc:oracle:thin:@localhost:1521:xe", "user", "pass", "oracle.jdbc.OracleDriver")
try {
def params = [
INTEGER(999), // Non-existent employee ID
out(VARCHAR), // Error message output
out(INTEGER) // Error code output
]
sql.call("{ call safe_update_employee(?, ?, ?) }", params) { outParams ->
def errorMessage = outParams[0]
def errorCode = outParams[1]
if (errorCode != 0) {
println "Procedure error ${errorCode}: ${errorMessage}"
} else {
println "Update successful"
}
}
} catch (SQLException e) {
println "SQL Error: ${e.message}"
}Install with Tessl CLI
npx tessl i tessl/maven-org-codehaus-groovy--groovy-sql