rdsdata

package
v1.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 14, 2026 License: MIT Imports: 27 Imported by: 0

README

RDS Data

Parity grade: A · SDK aws-sdk-go-v2/service/rdsdata@v1.35.4 · last audited 2026-09-04 (deb6c42f)

Coverage

Metric Value
PARITY entries audited 6 (6 ok)
Feature families 5 (5 ok)
Known gaps 3
Deferred items 0
Resource leaks clean
Known gaps
  • "Database/Schema (ExecuteStatement, BatchExecuteStatement, BeginTransaction, ExecuteSql -- all 4 ops that carry them) are decoded off the wire and never read anywhere (cmd/reqfieldscan, 2026-08-30 pass: 8 of rdsdata's 9 flagged fields). Real AWS's Database overrides the database named by resourceArn's connection/secret, and Schema (PostgreSQL only) overrides search_path -- both select within a resource. gopherstack's sqlEngine keys its one SQLite database per (region, resourceARN) only (engine.go's dbFor/dbKey); there is no per-resource multi-database or schema catalog for these fields to select into, the same root cause as ExecuteSql's Database/ Schema fields below and its siblings' repeated honest-gap pattern in this campaign. Confirmed via grep: no .Database/.Schema selector anywhere in non-test source. Not fixed: modeling multiple named databases/schemas inside one engine instance is a real feature (SQLite ATTACH DATABASE per name, or a schema-qualified table namespace), not a field-read fix."
  • "SqlParameter.typeHint bind semantics (gopherstack-fdle, fixed this pass -- see Notes): a hint now validates its stringValue's documented format and 400s a malformed one, but the bound value is still the unmodified string -- the mock SQLite engine has no distinct DATE/ DECIMAL/TIMESTAMP/UUID column types to coerce into, so a well-formed DATE-hinted value still binds identically to an unhinted string. Real AWS's exact behavior for a malformed hinted value (which error class, and whether it's a request-time or DB-execution-time failure) is not independently verifiable without a live Aurora cluster -- the BadRequestException class and message wording gopherstack now returns are a best-effort inference, not a field-diffed fact. See Notes."
  • "ColumnMetadata.SchemaName/TableName/IsAutoIncrement (gopherstack-fdle, fixed this pass for the non-transactional path -- see Notes): populated via modernc.org/sqlite@v1.58.0's conn.ColumnInfo, which exposes the real sqlite3_column_table_name/database_name/origin_name C APIs through *sql.Conn.Raw (database/sql's own sql.ColumnType has no such accessor, as the prior pass found). Still always zero-valued for a statement run inside a BeginTransaction transaction: *sql.Tx has no equivalent to *sql.Conn.Raw, so there's no way to recover the driver connection ColumnInfo needs. ArrayBaseColumnType remains always 0 -- unaffected, and correct, since this mock's result columns are never array-typed (see the field_union family note above)."

More

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrTransactionNotFound is returned when a transaction does not exist.
	ErrTransactionNotFound = awserr.New("TransactionNotFoundException", awserr.ErrNotFound)
	// ErrValidation is returned when input validation fails.
	ErrValidation = awserr.New("BadRequestException", awserr.ErrInvalidParameter)
)
View Source
var ErrNilAppContext = errors.New("nil AppContext passed to RDSData Provider.Init")

ErrNilAppContext is returned by Init when a nil AppContext is passed.

Functions

This section is empty.

Types

type ArrayValue added in v1.2.0

type ArrayValue struct {
	ArrayValues   []ArrayValue `json:"arrayValues,omitempty"`
	BooleanValues []bool       `json:"booleanValues,omitempty"`
	DoubleValues  []float64    `json:"doubleValues,omitempty"`
	LongValues    []int64      `json:"longValues,omitempty"`
	StringValues  []string     `json:"stringValues,omitempty"`
}

ArrayValue represents an array of values, mirroring the real API's ArrayValue union (types.ArrayValue in aws-sdk-go-v2/service/rdsdata). Exactly one member is meaningfully populated at a time, matching the real union's shape.

type ColumnMetadata

type ColumnMetadata struct {
	Name                string `json:"name"`
	Label               string `json:"label"`
	TypeName            string `json:"typeName"`
	SchemaName          string `json:"schemaName"`
	TableName           string `json:"tableName"`
	Type                int32  `json:"type"`
	ArrayBaseColumnType int32  `json:"arrayBaseColumnType"`
	Nullable            int32  `json:"nullable"`
	Precision           int32  `json:"precision"`
	Scale               int32  `json:"scale"`
	IsAutoIncrement     bool   `json:"isAutoIncrement"`
	IsCaseSensitive     bool   `json:"isCaseSensitive"`
	IsCurrency          bool   `json:"isCurrency"`
	IsSigned            bool   `json:"isSigned"`
}

ColumnMetadata describes a single column returned by a SQL statement. Field set mirrors the real RDS Data API shape (types.ColumnMetadata in aws-sdk-go-v2/service/rdsdata); see engine.go's columnMetadataFor for how each field is derived from the pure-Go SQLite driver's limited column introspection.

type ExecutedStatement

type ExecutedStatement struct {
	SQL           string `json:"sql"`
	ResourceARN   string `json:"resourceArn"`
	TransactionID string `json:"transactionId,omitempty"`
}

ExecutedStatement represents a record of an executed SQL statement.

type Field

type Field struct {
	IsNull       *bool       `json:"isNull,omitempty"`
	BooleanValue *bool       `json:"booleanValue,omitempty"`
	LongValue    *int64      `json:"longValue,omitempty"`
	DoubleValue  *float64    `json:"doubleValue,omitempty"`
	StringValue  *string     `json:"stringValue,omitempty"`
	ArrayValue   *ArrayValue `json:"arrayValue,omitempty"`
	BlobValue    []byte      `json:"blobValue,omitempty"`
}

Field represents a single field value in an RDS Data API record.

ArrayValue is modeled for wire completeness (it is a real member of the SDK's Field union -- types.FieldMemberArrayValue) even though this mock can never populate it in a result: real AWS documents "Array parameters are not supported" for ExecuteStatementInput.Parameters (see validateNoArrayParameters in handler.go, which rejects it on the way in), and the pure-Go SQLite driver backing the mock engine never produces an array-typed result column. See PARITY.md.

type Handler

type Handler struct {
	Backend StorageBackend

	AccountID string
	Region    string
	// contains filtered or unexported fields
}

Handler is the HTTP handler for the RDS Data REST API.

func NewHandler

func NewHandler(backend StorageBackend) *Handler

NewHandler creates a new RDS Data handler.

func (*Handler) ChaosOperations

func (h *Handler) ChaosOperations() []string

ChaosOperations returns all operations that can be fault-injected.

func (*Handler) ChaosRegions

func (h *Handler) ChaosRegions() []string

ChaosRegions returns all regions this handler handles.

func (*Handler) ChaosServiceName

func (h *Handler) ChaosServiceName() string

ChaosServiceName returns the lowercase AWS service name for fault rule matching.

func (*Handler) ExtractOperation

func (h *Handler) ExtractOperation(c *echo.Context) string

ExtractOperation extracts the operation name from the request path.

func (*Handler) ExtractResource

func (h *Handler) ExtractResource(_ *echo.Context) string

ExtractResource always returns an empty string for the RDS Data API. The resource is identified by a resourceArn in the request body, but parsing the body here would require double-buffering; metrics and logging can rely on ExtractOperation instead.

func (*Handler) GetSupportedOperations

func (h *Handler) GetSupportedOperations() []string

GetSupportedOperations returns the list of supported RDS Data operations.

func (*Handler) Handler

func (h *Handler) Handler() echo.HandlerFunc

Handler returns the Echo handler function for RDS Data requests.

func (*Handler) MatchPriority

func (h *Handler) MatchPriority() int

MatchPriority returns the routing priority.

func (*Handler) Name

func (h *Handler) Name() string

Name returns the service name.

func (*Handler) Reset

func (h *Handler) Reset()

Reset clears all handler and backend state. Useful for test isolation.

func (*Handler) Restore

func (h *Handler) Restore(ctx context.Context, data []byte) error

Restore implements persistence.Persistable by delegating to the backend.

func (*Handler) RouteMatcher

func (h *Handler) RouteMatcher() service.Matcher

RouteMatcher returns a function that matches RDS Data API requests. All path-based matches are gated on the SigV4 service name to prevent routing conflicts with other services that share similar REST paths.

func (*Handler) Snapshot

func (h *Handler) Snapshot(ctx context.Context) []byte

Snapshot implements persistence.Persistable by delegating to the backend.

Dead-wiring fix (Phase 3.3): InMemoryBackend already implemented Snapshot/Restore, but Handler never delegated to them, so cli.go's generic setupPersistence (which type-asserts the registered service.Registerable, i.e. the Handler, for a Snapshot/Restore pair) never picked RDSData up -- the backend's persistence logic existed but was never invoked. This delegation (matching the mediastore/codecommit/cleanrooms pattern) wires RDSData into persistence for the first time.

func (*Handler) StartWorker

func (h *Handler) StartWorker(ctx context.Context) error

StartWorker starts the background janitor if configured.

func (*Handler) WithJanitor

func (h *Handler) WithJanitor(backend *InMemoryBackend, interval, idleTimeout, maxLifetime time.Duration,
	taskTimeout ...time.Duration,
) *Handler

WithJanitor attaches a background Janitor that expires transactions per BeginTransaction's documented lifetime (see janitor.go). backend must be the same *InMemoryBackend passed to NewHandler -- the Janitor needs direct map access the StorageBackend interface doesn't expose.

type InMemoryBackend

type InMemoryBackend struct {
	// contains filtered or unexported fields
}

InMemoryBackend is an in-memory RDS Data backend.

All resource maps are nested by region (outer key = region) so that same-named resources are isolated across regions. The per-region inner maps / tables are created lazily via the *Store helpers. Callers must hold b.mu while accessing them. See store_setup.go for why transactions is a map[string]*store.Table[Transaction] while executedStatements and txCounter remain plain maps.

func NewInMemoryBackend

func NewInMemoryBackend(accountID, region string) *InMemoryBackend

NewInMemoryBackend creates a new in-memory RDS Data backend.

func (*InMemoryBackend) AccountID

func (b *InMemoryBackend) AccountID() string

AccountID returns the AWS account ID this backend is configured for.

func (*InMemoryBackend) AddTransactionInternal

func (b *InMemoryBackend) AddTransactionInternal(txID string)

AddTransactionInternal directly inserts a transaction into the backend's default region. This is intended only for seeding test data.

func (*InMemoryBackend) BatchExecuteStatement

func (b *InMemoryBackend) BatchExecuteStatement(
	ctx context.Context,
	resourceARN, sql, transactionID string,
	parameterSets [][]SQLParameter,
) ([]UpdateResult, error)

BatchExecuteStatement executes a batch of SQL statements and returns results for each.

func (*InMemoryBackend) BeginTransaction

func (b *InMemoryBackend) BeginTransaction(ctx context.Context, resourceARN string) (string, error)

BeginTransaction starts a new transaction and returns its ID.

func (*InMemoryBackend) CommitTransaction

func (b *InMemoryBackend) CommitTransaction(
	ctx context.Context,
	transactionID string,
) (string, error)

CommitTransaction commits a transaction by ID.

func (*InMemoryBackend) ExecuteSQL

func (b *InMemoryBackend) ExecuteSQL(
	ctx context.Context,
	resourceARN, sqlStatements string,
) ([]SQLStatementResult, error)

ExecuteSQL executes one or more SQL statements against the cluster. This is a deprecated operation; use ExecuteStatement or BatchExecuteStatement instead.

func (*InMemoryBackend) ExecuteStatement

func (b *InMemoryBackend) ExecuteStatement(
	ctx context.Context,
	resourceARN, sql, transactionID string,
	parameters ...SQLParameter,
) ([][]Field, []ColumnMetadata, int64, []Field, error)

ExecuteStatement executes a SQL statement and returns its result set. Named parameters (e.g. ":id") are bound when supplied. The returned generated fields are non-empty only for an INSERT into a table with a single INTEGER PRIMARY KEY column -- see generatedFieldsFor in engine.go.

func (*InMemoryBackend) ListExecutedStatements

func (b *InMemoryBackend) ListExecutedStatements(ctx context.Context) []ExecutedStatement

ListExecutedStatements returns a copy of all executed statements for the request's region.

func (*InMemoryBackend) ListTransactions

func (b *InMemoryBackend) ListTransactions(ctx context.Context) map[string]Transaction

ListTransactions returns a deep copy of all active transactions for the request's region.

func (*InMemoryBackend) Region

func (b *InMemoryBackend) Region() string

Region returns the AWS region this backend is configured for.

func (*InMemoryBackend) Reset

func (b *InMemoryBackend) Reset()

Reset clears all backend state. Useful for test isolation.

func (*InMemoryBackend) Restore

func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error

Restore loads backend state from a JSON snapshot.

func (*InMemoryBackend) RollbackTransaction

func (b *InMemoryBackend) RollbackTransaction(
	ctx context.Context,
	transactionID string,
) (string, error)

RollbackTransaction rolls back a transaction by ID.

func (*InMemoryBackend) Snapshot

func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte

Snapshot serialises the backend state to JSON.

func (*InMemoryBackend) WithClock

func (b *InMemoryBackend) WithClock(now func() time.Time) *InMemoryBackend

WithClock overrides the backend's time source, used by tests to drive transaction idle-timeout/max-lifetime expiry (janitor.go) deterministically -- no time.Sleep, no real wall-clock waits.

type Janitor

type Janitor struct {
	Backend     *InMemoryBackend
	Interval    time.Duration
	IdleTimeout time.Duration
	MaxLifetime time.Duration
	// TaskTimeout bounds each individual sweep. When non-zero, each sweep
	// runs with a child context that expires after this duration, preventing
	// a stalled operation from blocking the janitor loop indefinitely.
	TaskTimeout time.Duration
}

Janitor is the RDS Data background worker that rolls back and evicts transactions real AWS would itself have expired by now: idle past IdleTimeout, or open past MaxLifetime (see the constants above). Without this, a caller that begins a transaction and never commits or rolls it back leaks it forever -- both the backend's Transaction record and the engine's open *sql.Tx (engine.go's sqlEngine.txs).

func NewJanitor

func NewJanitor(backend *InMemoryBackend, interval, idleTimeout, maxLifetime time.Duration) *Janitor

NewJanitor creates a new RDS Data Janitor for the given backend. Zero values for interval, idleTimeout, or maxLifetime fall back to the AWS-documented defaults above.

func (*Janitor) Run

func (j *Janitor) Run(ctx context.Context)

Run runs the janitor loop until ctx is cancelled.

func (*Janitor) SweepOnce

func (j *Janitor) SweepOnce(ctx context.Context)

SweepOnce runs a single janitor pass. Exposed for testing.

type Provider

type Provider struct{}

Provider implements service.Provider for RDS Data.

func (*Provider) Init

Init initializes the RDS Data service backend and handler.

func (*Provider) Name

func (p *Provider) Name() string

Name returns the provider name.

type Record added in v1.3.1

type Record struct {
	Values []Value `json:"values"`
}

Record is a single row of a ResultFrame (types.Record in aws-sdk-go-v2/service/rdsdata, deserializers.go:2865).

type ResultFrame added in v1.3.1

type ResultFrame struct {
	ResultSetMetadata *ResultSetMetadata `json:"resultSetMetadata,omitempty"`
	Records           []Record           `json:"records"`
}

ResultFrame is the result set of a single ExecuteSql statement (types.ResultFrame, deserializers.go:2913). It is left nil for statements that don't produce rows -- see SQLStatementResult.

type ResultSetMetadata added in v1.3.1

type ResultSetMetadata struct {
	ColumnMetadata []ColumnMetadata `json:"columnMetadata"`
	ColumnCount    int64            `json:"columnCount"`
}

ResultSetMetadata describes the columns of a ResultFrame (types.ResultSetMetadata, deserializers.go:2954).

type SQLParameter

type SQLParameter struct {
	Name     string `json:"name"`
	TypeHint string `json:"typeHint,omitempty"`
	Value    Field  `json:"value"`
}

SQLParameter represents a named parameter for a SQL statement. TypeHint mirrors the real API's DATE/DECIMAL/JSON/TIME/TIMESTAMP/UUID hint values; it is accepted on the wire but does not change bind behavior since the mock SQLite engine has no distinct DATE/TIMESTAMP/UUID column types to convert to (see PARITY.md).

type SQLStatementResult

type SQLStatementResult struct {
	ResultFrame            *ResultFrame `json:"resultFrame,omitempty"`
	NumberOfRecordsUpdated int64        `json:"numberOfRecordsUpdated"`
}

SQLStatementResult represents the result of a single SQL statement in an ExecuteSql call.

type StorageBackend

type StorageBackend interface {
	// Statement execution
	ExecuteStatement(
		ctx context.Context,
		resourceARN, sql, transactionID string,
		parameters ...SQLParameter,
	) ([][]Field, []ColumnMetadata, int64, []Field, error)
	BatchExecuteStatement(
		ctx context.Context,
		resourceARN, sql, transactionID string,
		parameterSets [][]SQLParameter,
	) ([]UpdateResult, error)
	ExecuteSQL(ctx context.Context, resourceARN, sqlStatements string) ([]SQLStatementResult, error)

	// Transaction management
	BeginTransaction(ctx context.Context, resourceARN string) (string, error)
	CommitTransaction(ctx context.Context, transactionID string) (string, error)
	RollbackTransaction(ctx context.Context, transactionID string) (string, error)

	// Introspection helpers (used by tests and dashboard)
	ListExecutedStatements(ctx context.Context) []ExecutedStatement
	ListTransactions(ctx context.Context) map[string]Transaction

	// Lifecycle
	Reset()
	Region() string
	AccountID() string
	Snapshot(ctx context.Context) []byte
	Restore(ctx context.Context, data []byte) error
}

StorageBackend defines the interface for RDS Data backend implementations. All methods must be safe for concurrent use.

type Transaction

type Transaction struct {
	CreatedAt      time.Time `json:"createdAt"`
	LastActivityAt time.Time `json:"lastActivityAt"`
	TransactionID  string    `json:"transactionId"`
	Status         string    `json:"status"`
}

Transaction represents an in-progress database transaction.

CreatedAt and LastActivityAt back the Janitor's expiry rules (janitor.go), which mirror BeginTransaction's documented lifetime (rdsdata@v1.35.4 api_op_BeginTransaction.go): a transaction is rolled back automatically after 24 hours, or after 3 minutes with no call using its transaction ID.

type UpdateResult

type UpdateResult struct {
	GeneratedFields []Field `json:"generatedFields"`
}

UpdateResult represents the result of a single update in a batch.

GeneratedFields is populated with the rowid-alias INTEGER PRIMARY KEY value assigned by an INSERT, when the target table declares exactly one such column (see generatedFieldsFor in engine.go). It is left empty for every other statement shape, matching real AWS ("generatedFields ... isn't supported by Aurora PostgreSQL").

type Value added in v1.3.1

type Value struct {
	IsNull      *bool    `json:"isNull,omitempty"`
	BitValue    *bool    `json:"bitValue,omitempty"`
	BigIntValue *int64   `json:"bigIntValue,omitempty"`
	DoubleValue *float64 `json:"doubleValue,omitempty"`
	StringValue *string  `json:"stringValue,omitempty"`
	BlobValue   []byte   `json:"blobValue,omitempty"`
}

Value represents a single field value in the deprecated ExecuteSql result set -- the older Value union (types.Value in aws-sdk-go-v2/service/rdsdata, deserializers.go:3496), distinct from Field: bigIntValue/bitValue instead of longValue/booleanValue. No arrayValues/intValue/realValue/structValue members: the mock engine's row extraction (engine.go's fieldFromValue) never produces those.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL