RDS Data API
Run real SQL over HTTP with the RDS Data API (ExecuteStatement) against fakecloud's real PostgreSQL and MySQL containers — typed parameters and results, including binary round-trips.
fakecloud implements the RDS Data API (rds-data) against the same real Docker-backed database containers the RDS service manages. ExecuteStatement runs your SQL on a genuine PostgreSQL or MySQL/MariaDB engine and returns AWS-shaped typed Field records — this is the wedge: other local emulators serve canned rows or return {} for binary columns, while fakecloud runs the real query.
Supported features
- ExecuteStatement — runs the SQL against the DB the
resourceArnresolves to (DB instance or Aurora cluster ARN), on the real container engine. - Typed parameters —
:namenamed parameters withstringValue,longValue,doubleValue,booleanValue,blobValue, andisNull, coerced to the column's real type. - Typed results —
recordsas typedFields (integers ->longValue, text ->stringValue,bytea/BLOB->blobValue, etc.), with optionalcolumnMetadata(includeResultMetadata) andformattedRecords(formatRecordsAs=JSON). Writes reportnumberOfRecordsUpdated. - Binary round-trips — a
bytea/BLOBcolumn round-trips throughblobValue, where rival emulators return an empty value. - Transactions —
BeginTransactionreturns atransactionIdbacked by a real database connection held open across requests.ExecuteStatementandBatchExecuteStatementcalls that pass thetransactionIdrun on that same connection, andCommitTransaction/RollbackTransactioncommit or roll back the genuine engine transaction. - BatchExecuteStatement — runs one statement across many
parameterSets, returning oneupdateResultsentry per set, on a single connection (the transaction's connection when atransactionIdis given).
Example
import boto3
data = boto3.client("rds-data", endpoint_url="http://localhost:4566")
arn = "arn:aws:rds:us-east-1:123456789012:db:mydb"
secret = "arn:aws:secretsmanager:us-east-1:123456789012:secret:db"
data.execute_statement(resourceArn=arn, secretArn=secret,
sql="CREATE TABLE t (id int, name text)")
data.execute_statement(resourceArn=arn, secretArn=secret,
sql="INSERT INTO t (id, name) VALUES (:id, :name)",
parameters=[{"name": "id", "value": {"longValue": 1}},
{"name": "name", "value": {"stringValue": "alice"}}])
resp = data.execute_statement(resourceArn=arn, secretArn=secret,
sql="SELECT id, name FROM t", includeResultMetadata=True)
# resp["records"] -> [[{"longValue": 1}, {"stringValue": "alice"}]]Transactions and batch writes share one held connection:
tx = data.begin_transaction(resourceArn=arn, secretArn=secret)["transactionId"]
data.batch_execute_statement(resourceArn=arn, secretArn=secret, transactionId=tx,
sql="INSERT INTO t (id, name) VALUES (:id, :name)",
parameterSets=[
[{"name": "id", "value": {"longValue": 2}}, {"name": "name", "value": {"stringValue": "bob"}}],
[{"name": "id", "value": {"longValue": 3}}, {"name": "name", "value": {"stringValue": "carol"}}],
])
data.commit_transaction(resourceArn=arn, secretArn=secret, transactionId=tx)