Skip to main content

SqlToDatabaseModule Migration Guide

Overview

SqlToDatabaseModule is a retired compatibility shell. Version 1.0 accepted a caller-controlled JDBC URL, plaintext username and password, arbitrary SQL, named parameters, batch input, and transaction flags. It opened any driver-supported destination from the workflow worker, could execute reads or irreversible writes, returned unbounded rows and generated keys, surfaced raw provider errors, and labeled every operation idempotent. Workflow Studio also advertised a separate SqlToDatabaseConnectorModule class that did not exist in the backend while claiming two-database synchronization behavior.

Version 2.0 keeps the real Java class and Spring bean loadable so saved workflows can be inspected and migrated, but hides it from backend discovery and removes the phantom frontend fallback entry. Execution now fails closed with MODULE_RETIRED, performs no credential, driver, DNS, socket, database, query, transaction, batch, or mutation operation, and returns provider-specific migration targets.

Usage

  1. Find saved tasks whose class is com.valkyrlabs.workflow.modules.database.SqlToDatabaseModule or whose fallback type is connector.sql.to_db.
  2. Remove legacy JDBC URLs, usernames, passwords, SQL, and parameters. Rotate credentials if their prior execution or exposure is uncertain.
  3. Identify the actual provider, exact operation, selected fields, result limit, mutation intent, and reconciliation key.
  4. Replace the task with a governed provider-specific connector such as SnowflakeModule, GoogleBigQueryModule, SupabaseModule, or MongoDBModule only when that connector supports the required operation.
  5. Bind a least-privilege IntegrationAccount in exact READY state. Do not copy credentials or arbitrary provider endpoints into module data.
  6. Prefer an allowlisted provider operation over caller-authored SQL. For a write, require the connector's explicit confirmation and reconcile ambiguous provider state before retrying.

Inputs

The compatibility shell accepts legacy field names only so saved task configuration can be identified. It ignores every value.

InputTypeActive behavior
jdbc_urlstringIgnored; never parsed, resolved, or contacted.
usernamestringIgnored; never used or emitted.
passwordstringIgnored; never used or emitted.
sqlstringIgnored; never parsed, prepared, or executed.
parametersobjectIgnored; never bound to a statement.
batch_modebooleanIgnored; no batch is prepared.
transactionbooleanIgnored; no transaction is opened.

Replacement inputs depend on the provider. Use fixed provider destinations, allowlisted operations and identifiers, bounded payloads and results, and explicit write controls.

Outputs

The retired module always returns:

OutputTypeDescription
statusstringAlways error.
errorobjectSafe MODULE_RETIRED, retryable:false, migration targets, and required action.

It never returns rows, row counts, affected-row counts, generated keys, batch sizes, connection details, SQL text, credentials, JDBC errors, or provider messages.

IntegrationAccount Requirements

SqlToDatabaseModule never resolves an IntegrationAccount; no account, raw credential, configuration flag, or workflow role can re-enable it.

For the replacement:

  • bind a provider-specific account in exact READY state;
  • grant only the database, schema, table, and operation privileges required by the workflow;
  • keep credentials in IntegrationAccount SecureFields;
  • fix the provider destination in the connector rather than accepting a workflow-controlled JDBC URL;
  • separate read and mutation accounts when practical; and
  • preserve provider receipts, caller correlation keys, and optimistic-concurrency values needed for reconciliation.

Configuration

The retired module has no active configuration. Saved JDBC URLs, usernames, passwords, SQL, named parameters, batch flags, and transaction flags are ignored.

A governed provider-specific write resembles:

{
"operation": "upsert_rows",
"table": "approved_customers",
"rows": [{ "external_id": "cust-42", "status": "active" }],
"confirm_write": true,
"correlation_key": "customer-sync-cust-42"
}

The exact fields vary by provider. Use only an operation documented by the selected connector; do not send the example to a provider that lacks the same contract.

Operations

SqlToDatabaseModule supports one compatibility operation: reject execution and identify migration targets. It does not load a JDBC driver, connect, authenticate, prepare SQL, bind parameters, read rows, begin or commit a transaction, batch statements, retry, or mutate data.

Provider-specific replacements expose only their documented operations. For example, Supabase provides bounded PostgREST row operations and RPC calls through a fixed project origin, while MongoDB exposes bounded document operations through its own IntegrationAccount contract. Choose the connector that matches the actual provider rather than treating generic SQL as a transport.

Errors and Failure Modes

FailureBehaviorRecovery
Any legacy executionReturns MODULE_RETIRED with retryable:false.Replace the task; retries cannot restore JDBC access.
Saved raw credential or credential-bearing JDBC URLThe value is ignored and not emitted.Remove and rotate it if prior exposure is uncertain.
Unknown or unsupported providerNo generic JDBC fallback is attempted.Add or harden a provider-specific connector with IntegrationAccount support.
Replacement account is not READYProvider module fails before sending a request.Repair or reauthorize the account.
Replacement read exceeds its boundProvider module fails with its documented size or page error.Narrow fields, filters, page size, or total limit.
Replacement write times out or returns an ambiguous responseThe write is not assumed successful and must not be blindly replayed.Reconcile provider state using its receipt or correlation key.
Replacement rejects a destructive operationNo mutation occurs.Use an allowlisted operation and obtain the required confirmation or approval.

Example

A saved legacy task reaches the compatibility shell:

{
"jdbc_url": "jdbc:postgresql://db.internal/app",
"username": "workflow_writer",
"password": "redacted",
"sql": "UPDATE accounts SET active = false WHERE id = :id",
"parameters": { "id": 42 },
"transaction": true
}

Expected result:

{
"status": "error",
"error": {
"code": "MODULE_RETIRED",
"message": "SqlToDatabaseModule is retired; use an approved provider-specific database connector",
"retryable": false,
"migrationTargets": [
"SnowflakeModule",
"GoogleBigQueryModule",
"SupabaseModule",
"MongoDBModule"
]
}
}

Notes

  • Pagination: the compatibility shell never paginates because it performs no read. Configure provider-native cursors, page sizes, and total result bounds on the replacement.
  • Limits: the shell returns a two-field response immediately and never materializes SQL, parameters, rows, batches, or generated keys.
  • Idempotency: the retired response is deterministic and side-effect free. Version 1.0's universal idempotency claim was false for arbitrary SQL writes. A replacement write is idempotent only when the provider contract and caller-owned key prove it.
  • API constraints: generic JDBC destinations, driver selection, arbitrary SQL, and credentials in workflow state are no longer accepted. Each replacement must fix or strictly derive its provider origin and enforce its own allowlist.
  • Destructive behavior: the shell cannot mutate data. Replacement deletes, bulk updates, DDL, stored procedures, or other irreversible operations require a provider-specific contract, explicit confirmation, and independent reconciliation.
  • Runtime deployment: source, tests, frontend fallback, and documentation can be merged and published independently, but live Workflow Studio continues to show version 1.0 until a normal backend deployment includes version 2.0.
  • Unverified boundary: deterministic tests prove fail-closed output, secret non-disclosure, repeatability, discovery exclusion, direct compatibility lookup, and frontend fallback removal. No live database request is performed because the retired module intentionally has no provider behavior.