SQL plugin
Overview
The SQL plugin connects QALIPSIS to relational databases through R2DBC. It is designed to insert test data, execute parameterized read queries, and continuously poll tables or views for new rows during a scenario.
- Technology addressed
-
SQL databases via R2DBC: PostgreSQL, MariaDB, MySQL, Microsoft SQL Server, Oracle Database.
- Dependency
-
io.qalipsis.plugin:qalipsis-plugin-sql - Namespace in scenario
-
sql() - Client library
-
R2DBC SPI with
r2dbc-pooland vendor drivers for PostgreSQL, MariaDB, MySQL, Microsoft SQL Server, and Oracle Database.
Supported steps
Poll step
The poll step periodically executes an ordered query and forwards the rows that match it.
- Ancestor
-
Scenario
- Functionality
-
The
pollstep is created from the scenario namespace. On each execution, it runs the configuredSELECT, emits the returned rows, remembers the value of the firstORDER BYcolumn from the last row of the batch, and reuses that value on the next poll to continue from the latest seen record. - Example
-
sql().poll { name = "poll-new-events" protocol(Protocol.POSTGRESQL) (1) connection { (2) port = 5432 database = "qalipsis" username = "qalipsis" password = "qalipsis" } query( (3) """ select id, device, eventname from events where device <> ? order by id """.trimIndent() ) parameters("Truck #1") (4) pollDelay(Duration.ofSeconds(1)) (5) }.flatten() (6)1 Select the SQL dialect used to create the connection pool and rewrite placeholders if needed. 2 Configure the connection details for the target database. 3 Declare the ordered SELECTstatement. The firstORDER BYcolumn (id) is used automatically as the poll tie-breaker.4 Bind the query parameter in the same order as the ?placeholder.5 Wait one second between two polling executions. 6 Emits each row individually as DatasourceRecord<Map<String, Any?>>instead of forwarding a fullSqlPollResultsbatch.
The poll step derives its tie-breaker automatically from the first column in the ORDER BY clause of query.
The plugin parses the SQL statement using Apache Calcite. After the first successful poll, it appends a condition on the tie-breaker column and adds the latest tie-breaker value as an extra prepared-statement parameter.
Use placeholders with ? for the parameters you configure explicitly through parameters(…). The generated tie-breaker parameter is appended by the plugin and must not be added manually.
When the query uses reserved identifiers, escape them using the quoting style expected by the target database. Refer to your database vendor documentation for details.
- Reference Documentation
-
Refer to your database vendor documentation for the exact SQL dialect and data types.
Save step
The save step inserts one or more rows into a SQL table.
- Ancestor
-
Step
- Functionality
-
The
savestep builds anINSERT INTO … VALUES …statement from the table name and column list, then executes it for eachSqlSaveRecordproduced from the current input and step context. - Example
-
.sql() (1) .save { name = "save-entry" protocol(Protocol.POSTGRESQL) (2) connection { (3) port = 5432 database = "qalipsis" username = "qalipsis" password = "qalipsis" } tableName { stepContext, input -> "buildingentries" } (4) columns { stepContext, input -> listOf("timestamp", "action", "username", "enabled") } (5) values { stepContext, input -> (6) listOf( SqlSaveRecord( input.timestamp, input.action, input.username, input.enabled ) ) } }1 Enter the SQL plugin namespace from the previous step. 2 Select the target SQL dialect. 3 Configure the connection pool for the save step. 4 Resolve the table to insert into. 5 Declare the ordered list of destination columns. 6 Build the rows to insert. The order of values in SqlSaveRecordmust match the order ofcolumnsexactly.
The save step builds an INSERT INTO … VALUES … prepared statement from tableName, columns, and values.
Each SqlSaveRecord represents one row. The plugin sends rows by batches to optimize the performances, and the order of values in SqlSaveRecord must exactly match the order of columns.
The save output is SqlSaveResult<I>, which exposes the original input via result.input, the generated identifiers supported by the driver via result.resultIds, and execution metrics via result.sqlSaveStepMeters.
- Reference Documentation
-
Refer to the documentation of your target SQL database for table definitions, constraints, and generated key behavior.
Search step
The search step executes a parameterized query and forwards the matching rows together with the original input.
- Ancestor
-
Step
- Functionality
-
The
searchstep computes the query and parameters from the current input and step context, executes the statement, and returns the rows asSqlSearchBatchResults<I, Map<String, Any?>>. - Example
-
.sql() (1) .search { name = "search-entries" protocol(Protocol.POSTGRESQL) (2) connection { (3) port = 5432 database = "qalipsis" username = "qalipsis" password = "qalipsis" } query { stepContext, input -> (4) """ select id, username, enabled from buildingentries where action = ? and enabled = ? order by id """.trimIndent() } parameters { stepContext, input -> (5) listOf(input.action, input.enabled) } }1 Enter the SQL plugin namespace from the previous step. 2 Select the target SQL dialect. 3 Configure the connection pool for the search step. 4 Build the SQL query dynamically from the current input and step context. 5 Provide the parameter values in the same order as the ?placeholders in the query. - Tip
-
The returned rows are available as
result.records. EachSqlSearchRecord.valueis aMap<String, Any?>keyed by lower-cased column names, for examplerecord.value["username"]. - Reference Documentation
-
Refer to your database documentation for the supported SQL syntax, indexes, and query tuning recommendations.
Configuration
DSL parameters
Available properties are described in the table below.
| Property | Description |
|---|---|
|
Configures the database connection pool for the step. The same block is available inside +
Applicable Steps: Poll, Search, Save + .Example
|
|
Host name of the database server. +
Applicable Steps: Poll, Search, Save + .Example
|
|
Port of the database server. +
Applicable Steps: Poll, Search, Save + .Example
|
|
Name of the target database or schema catalog passed to the R2DBC connection factory. +
Applicable Steps: Poll, Search, Save + .Example
|
|
Username used to authenticate to the database. +
Applicable Steps: Poll, Search, Save + .Example
|
|
Password used to authenticate to the database. +
Applicable Steps: Poll, Search, Save + .Example
|
|
Maximum number of connections in the R2DBC pool. +
Applicable Steps: Poll, Search, Save + .Example
|
|
Maximum duration a pooled connection can stay idle before being recycled. +
Applicable Steps: Poll, Search, Save + .Example
|
|
Timeout used while establishing a new connection to the database. +
Applicable Steps: Poll, Search, Save + .Example
|
|
Optional application name stored on the +
Applicable Steps: Poll, Search, Save + .Example
|
|
Optional extra options stored on the +
Applicable Steps: Poll, Search, Save + .Example
|
|
Selects the SQL dialect. The dialect drives the connection factory and rewrites the DSL placeholders to the vendor-specific syntax when necessary. + .Example
|
|
Defines the SQL statement to execute. +
Applicable Steps: Poll, Search +
For Poll, the statement must be an ordered +
All placeholders must be written as + .Example (Poll)
+ .Example (Search)
|
|
Ordered values bound to the placeholders in +
Applicable Steps: Poll, Search +
The order of the values must match the order of the + .Example (Poll)
+ .Example (Search)
|
|
Resolves the destination table for the +
Applicable Steps: Save + .Example
|
|
Resolves the ordered list of columns to populate in the generated +
Applicable Steps: Save + .Example
|
|
Produces the rows to insert. Each +
Applicable Steps: Save +
The save step does not batch records into one multi-row SQL statement; it inserts each + .Example
|
|
Delay between the end of one poll execution and the start of the next one. +
Applicable Steps: Poll + .Example
|
|
Changes the output of +
Applicable Steps: Poll + .Example
|
|
Configures how the results of +
Applicable Steps: Poll + .Example
+ Refer to SingletonConfiguration parameters for details on the available strategies. |
Shared defaults for SQL steps
You can define defaults once in the scenario section or just after, and let all following SQL steps inherit them.
scenario {
sql().defaults { (1)
connection {
host = "localhost"
port = 5432
database = "qalipsis"
username = "qalipsis"
password = "qalipsis"
}
protocol(Protocol.POSTGRESQL)
monitoring {
events = true
meters = true
}
}
}
| 1 | Defaults are applied to subsequent SQL steps in the same scenario. Individual steps can still override values. |