Aurora DSQL
The DNML operations for Amazon Aurora DSQL run SQL on a cluster and read its catalog. A request with one of these operations uses DNML version 1.1.
The examples on this page are parts of four complete example files. To run SQL outside a request, use the Aurora DSQL console.
Connection keys
Each Aurora DSQL operation connects to one cluster as one database role. Set the connection keys on the operation, or one time in [defaults].
| Key | Required | Rules |
|---|---|---|
clusterArn | Yes, on the operation or in [defaults] | The form is arn:aws:dsql:<region>:<account-id>:cluster/<cluster-id>. Dynomate resolves templates before it checks the ARN. An ARN that is not valid gives DNML_INVALID_CLUSTER_REFERENCE. |
databaseRole | Yes, on the operation or in [defaults] | For exactly admin, Dynomate signs a dsql:DbConnectAdmin token. For any other role, also Admin, it signs a dsql:DbConnect token. |
profileName | No | The AWS profile that signs the token. The default is the request default, then the profile named default. |
region | No | It must be the AWS Region in the cluster ARN, or the error is DNML_REGION_MISMATCH. |
Aurora DSQL operations do not accept endpointUrl, database or tableArn. In the app, set the defaults in Request settings.
This part of inspect-orders.dnml gets the cluster ID from an input:
[defaults]profileName = "commerce-dev"clusterArn = "arn:aws:dsql:us-east-1:111122223333:cluster/${CLUSTER_ID}"databaseRole = "app_reader" Connections in a run
- A run opens one connection for each profile, cluster ARN and database role. Operations with the same three values share the connection, so a
SETstays for the later operations. - Each connection starts with
TimeZone=UTC,DateStyle=ISOandIntervalStyle=iso_8601. - The connection uses the saved network settings of the cluster ARN.
- After a cancellation, a deadline, a lost connection or a failed rollback, Dynomate closes the connection. Later operations on it fail in the same run.
- Aurora DSQL operations need no confirmation or approval, also as
admin. See Aurora DSQL connections.
Required permissions
A request needs dsql:DbConnect on the cluster, or dsql:DbConnectAdmin to connect as admin. It makes no Aurora DSQL API calls, because Dynomate signs the token on your computer. For an example policy, see connection permissions. A request does not need the dsql:GetCluster action of that policy.
Parameters
parameters gives the values for $1, $2 and so on, in order. Each value binds as a PostgreSQL parameter:
| DNML value | PostgreSQL parameter |
|---|---|
| An integer | int8 |
A float, for example 12.5 | float8 |
A boolean, or { BOOL = … } | bool |
A string, or { S = "…" } | No type. The server finds the type from the SQL, so a string matches a uuid column without a cast. |
{ N = "…" }, or an exact number from an earlier result | numeric |
{ B = "…" }, or binary from an earlier result | bytea |
{ NULL = true }, or null from an earlier result | NULL, with no type |
A map or a list: { M = … }, { L = … }, or a TOML table or array | jsonb |
A set: SS, NS or BS | Not permitted. The error is DNML_TYPE_MISMATCH. |
- With
parameters, the SQL must be one statement. Withoutparameters, the SQL can hold more than one statement. - For exact money values, use
{ N = "12.50" }. A TOML float binds asfloat8. - To reuse a decimal from an earlier result, use a whole-value template.
{ N = "${…}" }fails withDNML_TYPED_VALUE.
In this part of inspect-orders.dnml, the SQL casts the string $1 to interval, and $2 binds as int8:
[[dsql.query]]name = "Recent orders"sql = '''SELECT id, status, total, created_atFROM ordersWHERE created_at >= now() - $1::intervalORDER BY created_at DESCLIMIT $2'''parameters = ["7 days", 100]maxRows = 25 Dollar quotes
In DNML, $$ is the escape for one $, so a $$ … $$ body reaches Aurora DSQL as $ … $. Use a tagged dollar quote, for example $fn$ … $fn$. See Escaping in DNML.
Results
dsql.query and dsql.transaction return this result:
{ statements: [ { columns: [ { name, key, type } ], rows: [ { <key>: value } ], rowCount, truncated, rowsAffected, commandTag } ], attempts, elapsedMs } statementshas one entry for each statement that the server runs. TheBEGINandCOMMITthat Dynomate sends have no entry.- The rows use
key, which is the column name. Repeated column names get_2,_3and so on. - With
maxRows,truncatedis true if the server sent more rows than Dynomate kept.
Each value in rows gets a type from its PostgreSQL type:
| PostgreSQL type | Value in the result |
|---|---|
int2, int4, int8, oid | Integer |
numeric | Exact decimal |
float4, float8 | Number |
bool | Boolean |
bytea | Binary |
json, jsonb | Maps and lists |
| NULL | null |
Other types, for example text, uuid, dates and times | The text from the server. Dates and times use UTC and the ISO format. |
To use a value in a later operation, refer to the result by the normalized name of the operation, for example ${load_order.statements[0].rows[0].id}. For the CLI output, see Aurora DSQL results in the CLI.
Commit status and retries
When a dsql.query or dsql.transaction fails, details.commitStatus shows what happened to its changes, if Dynomate knows it:
commitStatus | Meaning |
|---|---|
committed | Aurora DSQL committed the changes before the error. |
rolled-back | The transaction rolled back. No changes were kept. |
unknown | Dynomate does not know if the commit completed. Check the data before you run the request again. |
An unknown outcome comes from an XX000 error, a cancellation, a deadline or a lost connection during a commit or an autocommit write. See Unknown commit outcomes.
Retry on conflict
By default, an optimistic concurrency conflict fails the operation. With retryOnConflict = true, Dynomate runs the full operation again after OC000 or OC001, up to 3 attempts in total. It does not retry after an unknown outcome or another error. timeoutMs includes all attempts.
In dsql-ledger.dnml, a retry is safe. The UPDATE reads the balance that it changes, and no value comes from an earlier operation:
[[dsql.transaction]]name = "Record payment"dependsOn = "Account"statements = [ { sql = "UPDATE ledger.accounts SET balance = balance - $2, updated_at = now() WHERE id = $1", parameters = ["${ACCOUNT_ID}", { N = "12.50" }], }, { sql = "INSERT INTO ledger.payments (account_id, amount) VALUES ($1, $2)", parameters = ["${ACCOUNT_ID}", { N = "12.50" }], },]retryOnConflict = true Aurora DSQL query
Runs SQL on an Aurora DSQL cluster in autocommit mode and returns the rows and command tag of each statement.
[defaults]profileName = "commerce-dev"clusterArn = "arn:aws:dsql:us-east-1:111122223333:cluster/exampleclusterid0123456789"databaseRole = "app_writer"[[dsql.query]]name = "Load order"sql = '''SELECT id, status, total, currencyFROM ordersWHERE id = $1 AND status = 'PENDING''''parameters = ["${ORDER_ID}"] - Each
dsql.queryis destructive, also aSELECT, but it needs no confirmation or approval. - Dynomate sends the SQL as written and adds no
LIMIT.maxRowsonly limits the rows that Dynomate keeps. - If the SQL leaves a transaction open, the result has the warning
DNML_DSQL_TRANSACTION_OPEN. A later operation on the same connection must runCOMMIT. If not, the transaction rolls back when the run ends.
[[dsql.query]] Destructive Keys
- clusterArn string
- The ARN of the Aurora DSQL cluster, in the form arn:aws:dsql:<region>:<account-id>:cluster/<id>. Dynomate gets the Region from it. Set it here or in [defaults]. In the app: Operation header › Cluster ARN
- databaseRole string
- The database role to connect as. For exactly admin, in lowercase, Dynomate signs a dsql:DbConnectAdmin token. For any other role, also Admin, it signs a dsql:DbConnect token. Set it here or in [defaults]. In the app: Operation header › Database role
- sql string Required
- The SQL to run in autocommit mode. Without parameters, it can hold several statements, and each statement returns its own result. With parameters, it must be one statement. In the app: SQL tab › SQL
- parameters array of values
- The values for $1, $2 and so on, in order. Dynomate sends a string with no type, and the server infers the type. A map or a list binds as jsonb. In the app: SQL tab › Parameters
- retryOnConflict boolean
- If true, Dynomate runs the full operation again after an optimistic concurrency conflict (OC000 or OC001), up to three attempts in total. The default is false. In the app: Execution tab › Retry on conflict
- maxRows integer
- The maximum number of rows that Dynomate keeps from each statement. The server still sends all rows. The default, 0, keeps all rows. In the app: no field. Edit the file.
DSQL transaction
Runs statements in one transaction, between BEGIN and COMMIT. If a statement fails, Dynomate rolls back the transaction.
[[dsql.transaction]]name = "Settle"dependsOn = "Load order"statements = [ { sql = "UPDATE orders SET status = 'SETTLED', settled_at = now() WHERE id = $1 AND status = 'PENDING'", parameters = ["${load_order.statements[0].rows[0].id}"], }, { sql = "INSERT INTO order_events (order_id, event, amount, currency) VALUES ($1, 'settled', $2, $3)", parameters = ["${load_order.statements[0].rows[0].id}", "${load_order.statements[0].rows[0].total}", "${load_order.statements[0].rows[0].currency}"], },] - If a statement fails, Dynomate sends
ROLLBACK.details.statementIndexnames the statement. - A statement that runs
COMMITorROLLBACKends the transaction early. The result then has the warningDNML_DSQL_TRANSACTION_ENDED. - The Aurora DSQL limits apply. For example, a transaction cannot mix DDL and DML. The 5-minute limit gives
DNML_AWS, notDNML_TIMEOUT. - Here,
retryOnConflictstaysfalse, because the values come from an earlier operation.
[[dsql.transaction]] Destructive Keys
- clusterArn string
- The ARN of the Aurora DSQL cluster, in the form arn:aws:dsql:<region>:<account-id>:cluster/<id>. Dynomate gets the Region from it. Set it here or in [defaults]. In the app: Operation header › Cluster ARN
- databaseRole string
- The database role to connect as. For exactly admin, in lowercase, Dynomate signs a dsql:DbConnectAdmin token. For any other role, also Admin, it signs a dsql:DbConnect token. Set it here or in [defaults]. In the app: Operation header › Database role
- statements array of maps Required
- The statements to run between BEGIN and COMMIT, in order. Each statement has sql and optional parameters. In the app: Statements tab › Statements
- retryOnConflict boolean
- If true, Dynomate runs the full transaction again after an optimistic concurrency conflict (OC000 or OC001), up to three attempts in total. The default is false. In the app: Execution tab › Retry on conflict
- maxRows integer
- The maximum number of rows that Dynomate keeps from each statement. The server still sends all rows. The default, 0, keeps all rows. In the app: no field. Edit the file.
List schemas
Lists the schemas in an Aurora DSQL cluster, without the system schemas.
[[dsql.listSchemas]]name = "Schemas"
The result has schemas and count. Each schema has name.
[[dsql.listSchemas]] Keys
- clusterArn string
- The ARN of the Aurora DSQL cluster, in the form arn:aws:dsql:<region>:<account-id>:cluster/<id>. Dynomate gets the Region from it. Set it here or in [defaults]. In the app: Operation header › Cluster ARN
- databaseRole string
- The database role to connect as. For exactly admin, in lowercase, Dynomate signs a dsql:DbConnectAdmin token. For any other role, also Admin, it signs a dsql:DbConnect token. Set it here or in [defaults]. In the app: Operation header › Database role
List DSQL tables
Lists the tables and views in one schema, with an optional name pattern.
[[dsql.listTables]]name = "Order tables"schema = "public"expression = "order%"
Here, order% matches orders and order_events. The result has tables and count. Each table has schema, name, kind, estimatedRows and comment.
[[dsql.listTables]] Keys
- clusterArn string
- The ARN of the Aurora DSQL cluster, in the form arn:aws:dsql:<region>:<account-id>:cluster/<id>. Dynomate gets the Region from it. Set it here or in [defaults]. In the app: Operation header › Cluster ARN
- databaseRole string
- The database role to connect as. For exactly admin, in lowercase, Dynomate signs a dsql:DbConnectAdmin token. For any other role, also Admin, it signs a dsql:DbConnect token. Set it here or in [defaults]. In the app: Operation header › Database role
- schema string Required
- The schema to list tables from. In the app: Operation header › Schema
- expression string
- A case-sensitive SQL LIKE pattern for table names, for example pay%. If you omit it, the operation lists all tables in the schema. In the app: Filter tab › Table name pattern
Describe DSQL table
Returns the columns, primary key, indexes and foreign keys of one table or view.
[[dsql.describeTable]]name = "Orders table"dependsOn = "Wait for index"schema = "public"tableName = "orders" - The result has
table, withcolumns,primaryKey,indexes,foreignKeys,estimatedRowsandcomment. - The
stateof each index isvalid,invalidorbuilding. - If the table does not exist, the operation fails with
DNML_AWSand the SQLSTATE42P01.
[[dsql.describeTable]] Keys
- clusterArn string
- The ARN of the Aurora DSQL cluster, in the form arn:aws:dsql:<region>:<account-id>:cluster/<id>. Dynomate gets the Region from it. Set it here or in [defaults]. In the app: Operation header › Cluster ARN
- databaseRole string
- The database role to connect as. For exactly admin, in lowercase, Dynomate signs a dsql:DbConnectAdmin token. For any other role, also Admin, it signs a dsql:DbConnect token. Set it here or in [defaults]. In the app: Operation header › Database role
- schema string
- The schema of the table. The default is public. In the app: Operation header › Schema
- tableName string Required
- The name of the table or view to describe. In the app: Operation header › Table
Wait for job
Waits until an asynchronous job, for example an index build, finishes.
[defaults]profileName = "commerce-admin"clusterArn = "arn:aws:dsql:us-east-1:111122223333:cluster/exampleclusterid0123456789"databaseRole = "admin"[[dsql.query]]name = "Create index"sql = "CREATE INDEX ASYNC orders_by_status ON orders (status, created_at)"[[dsql.waitForJob]]name = "Wait for index"dependsOn = "Create index"timeoutMs = 900000jobId = "${create_index.statements[0].rows[0].job_id}"pollIntervalMs = 2000 - Wait for index reads the job ID from the
job_idcolumn thatCREATE INDEX ASYNCreturns. - The default deadline is 30 minutes. Here,
timeoutMssets 15 minutes. statein the result iscompleted, orunknownif Aurora DSQL removed the job record. For an index job,indexValidthen shows if the index is valid.- A failed job fails the operation with
DNML_AWS.
[[dsql.waitForJob]] Keys
- clusterArn string
- The ARN of the Aurora DSQL cluster, in the form arn:aws:dsql:<region>:<account-id>:cluster/<id>. Dynomate gets the Region from it. Set it here or in [defaults]. In the app: Operation header › Cluster ARN
- databaseRole string
- The database role to connect as. For exactly admin, in lowercase, Dynomate signs a dsql:DbConnectAdmin token. For any other role, also Admin, it signs a dsql:DbConnect token. Set it here or in [defaults]. In the app: Operation header › Database role
- jobId string Required
- The job ID that an asynchronous statement returns, for example CREATE INDEX ASYNC. It is usually a reference to the result of that operation. In the app: Job tab › Job ID
- pollIntervalMs integer
- The time between job status checks, in milliseconds. The default is 1,000. In the app: Execution tab › Poll interval (ms)