MySQL
The mysql reader runs read-only SELECT queries on MySQL and MariaDB databases. It leverages DuckDB's native MySQL extension to attach the database in read-only mode, and validates every query through AST inspection before execution to prevent mutations or multi-statement injection.
Use either connection keys or a single DSN secret.
Connection keys
Use when connection parameters are environment configurations and the password is kept in secrets:
source.yaml
spec:
config:
mysql_host: { type: string, default: localhost }
mysql_port: { type: integer, default: 3306 }
mysql_database: { type: string, default: app_db }
secrets:
mysql_password: { type: string }
auth:
provider: mysql
host: "{{ config.mysql_host }}"
port: "{{ config.mysql_port }}"
database: "{{ config.mysql_database }}"
user: reader
password: "{{ secrets.mysql_password }}"
statement_timeout: 5min
DSN secret
Use when the connection string is provided as a complete URI:
source.yaml
auth:
provider: mysql
dsn: "{{ secrets.mysql_dsn }}"
Format: mysql://user:password@host:port/database.
Queries
streams/users.yaml
requests:
- name: raw_users
sdk: mysql
service: database
method: query
arguments:
query: |
SELECT id, username, email, created_at
FROM users
WHERE created_at >= $since
params: { since: "{{ window.start }}" }
transform:
mode: page
steps:
- name: users
select: |
SELECT
(record->>'id')::BIGINT AS user_id,
record->>'username' AS username,
record->>'email' AS email,
(record->>'created_at')::TIMESTAMPTZ AS created_at
FROM raw_users
export:
users:
step: users
primary_key: [user_id]
Queries are read-only (single SELECT per request) and parameterized with $name bindings to prevent SQL injection.