Skip to main content

edg-migrate

Convert an edg config between database drivers (e.g., pgx to mysql) or between formats (YAML to DSL, DSL to YAML).

Source facts

Repository
cockroachdb/demo-video-code
Last source activity
June 27, 2026 at 19:59
Detected SKILL.md language
English
Stars
6
Forks
2

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
edg-migrate
description
Convert an edg config between database drivers (e.g., pgx to mysql) or between formats (YAML to DSL, DSL to YAML).
user-invocable
true
# edg Config Migrator You convert edg workload configurations between database drivers and between formats (YAML ↔ DSL). Given a config written for one driver or format and a target, you produce a working config. ## Input The user provides: - A path to an existing edg config (YAML or DSL) - The source driver (infer from config if not stated) - The target driver and/or target format ## Migration Rules Apply the following transformations based on the source and target driver. edg handles placeholder conversion automatically (`$1` works for all drivers), so focus on SQL dialect differences. ### Type Mappings | Concept | pgx | mysql | mssql | oracle | mongodb | cassandra | |---|---|---|---|---|---|---| | UUID | `UUID` | `CHAR(36)` | `UNIQUEIDENTIFIER` | `VARCHAR2(36)` | *(string field)* | `UUID` | | UUID default | `DEFAULT gen_random_uuid()` | `DEFAULT (UUID())` | `DEFAULT NEWID()` | *(generate in args)* | *(generate in args)* | *(generate in args)* | | String | `STRING` or `VARCHAR(n)` | `VARCHAR(n)` | `NVARCHAR(n)` | `VARCHAR2(n)` | *(string field)* | `TEXT` | | Unlimited string | `TEXT` | `TEXT` | `NVARCHAR(MAX)` | `CLOB` | *(string field)* | `TEXT` | | Timestamp | `TIMESTAMP` | `TIMESTAMP` | `DATETIME2` | `TIMESTAMP` | *(ISODate field)* | `TIMESTAMP` | | Timestamp default | `DEFAULT now()` | `DEFAULT CURRENT_TIMESTAMP` | `DEFAULT GETDATE()` | `DEFAULT SYSTIMESTAMP` | *(generate in args)* | *(generate in args)* | | Boolean | `BOOL` | `TINYINT(1)` | `BIT` | `NUMBER(1)` | *(boolean field)* | `BOOLEAN` | | Auto-increment | *(use UUID)* | `AUTO_INCREMENT` | `IDENTITY(1,1)` | `GENERATED ALWAYS AS IDENTITY` | *(not applicable)* | *(not applicable)* | | Decimal | `DECIMAL(p,s)` | `DECIMAL(p,s)` | `DECIMAL(p,s)` | `NUMBER(p,s)` | *(number field)* | `DECIMAL` | | Integer | `INT` | `INT` | `INT` | `NUMBER(10)` | *(number field)* | `INT` | | Big integer | `BIGINT` | `BIGINT` | `BIGINT` | `NUMBER(19)` | *(number field)* | `BIGINT` | ### DDL Safety | Driver | CREATE pattern | DROP pattern | |---|---|---| | pgx | `CREATE TABLE IF NOT EXISTS ...` | `DROP TABLE IF EXISTS ...` | | mysql | `CREATE TABLE IF NOT EXISTS ...` | `DROP TABLE IF EXISTS ...` | | mssql | `IF OBJECT_ID('t', 'U') IS NULL CREATE TABLE t (...)` | `IF OBJECT_ID('t', 'U') IS NOT NULL DROP TABLE t` | | oracle | PL/SQL block with `EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;` | `DROP TABLE t CASCADE CONSTRAINTS PURGE` | | mongodb | `{"create": "collection"}` | `{"drop": "collection"}` | | cassandra | `CREATE TABLE IF NOT EXISTS ks.t (...)` | `DROP TABLE IF EXISTS ks.t` | ### Row Generation in Seed Queries | Driver | Pattern | |---|---| | pgx | `generate_series(1, $1)` | | mysql | `WITH RECURSIVE seq AS (SELECT 1 AS s UNION ALL SELECT s + 1 FROM seq WHERE s < $1) SELECT * FROM seq` | | mssql | `WITH seq AS (SELECT 1 AS s UNION ALL SELECT s + 1 FROM seq WHERE s < $1) SELECT * FROM seq OPTION (MAXRECURSION 0)` | | oracle | `SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= $1` | ### Batch Expansion (expanding CSV/JSON args into rows) | Driver | Pattern | |---|---| | pgx | `SELECT unnest(string_to_array('$1', __sep__))` | | mysql | `SELECT j.val FROM JSON_TABLE(CONCAT('["', REPLACE('$1', __sep__, '","'), '"]'), '$[*]' COLUMNS(val VARCHAR(255) PATH '$')) j` | | mssql | Use `batch_format: json` and `SELECT value FROM OPENJSON('$1')` | | oracle | `SELECT column_value FROM XMLTABLE(('"' \|\| REPLACE('$1', __sep__, '","') \|\| '"'))` | | mongodb | Not applicable; batch uses `exec_batch` with per-document `{"insert": ...}` commands | | cassandra | Not applicable; batch uses `exec_batch` with CQL `INSERT` statements (unlogged batch internally) | ### Multi-Row VALUES (`__values__` token) - Recommended Prefer `__values__` over driver-specific batch expansion. It generates a standard multi-row `VALUES` clause and works the same across pgx, mysql, mssql, spanner, and dsql - no driver-specific SQL needed: ```yaml - name: seed_users type: exec_batch count: 1000 size: 100 args: - gen('email') query: |- INSERT INTO t (email) __values__ ``` `__values__` also works with `type: exec`/`query` when using batch-expanding arg functions (`gen_batch()`, `batch()`, `ref_each()`). All arg sets are collapsed into a single VALUES clause: ```yaml - name: seed_ids type: exec args: - batch(5) query: |- INSERT INTO t (id) __values__ ``` When migrating between SQL drivers (pgx, mysql, mssql, spanner, dsql), `__values__` queries need no changes. For Oracle, use the parameterized form `__values__(table(col1, col2))` which generates `INSERT ALL INTO table (cols) VALUES (...) ... SELECT 1 FROM DUAL`. When migrating to/from MongoDB or Cassandra, convert to/from `__values__` and the driver-specific pattern above. When migrating old driver-specific batch patterns (OPENJSON, UNNEST/SPLIT, JSON_TABLE) to `__values__`: - Remove `batch_format: json` if present - Replace driver-specific SQL with `__values__` - Move any SQL-side arithmetic into arg expressions (e.g., `CAST(v3 AS INT) * 8` becomes `gen('number:0,2') * 8` in args) - Use `arg(N)` to share computed values across args in the same row - `gen_batch()` + `__values__` is supported (the CSV values are expanded into proper VALUES tuples) ### Upsert / Merge | Driver | Pattern | |---|---| | pgx | `ON CONFLICT (col) DO UPDATE SET ...` | | mysql | `ON DUPLICATE KEY UPDATE col = VALUES(col)` | | mssql | `MERGE INTO t USING (SELECT @p1 AS c1) src ON t.c1 = src.c1 WHEN MATCHED THEN UPDATE SET ... WHEN NOT MATCHED THEN INSERT ...;` | | oracle | `MERGE INTO t USING (SELECT :1 AS c1 FROM DUAL) src ON (t.c1 = src.c1) WHEN MATCHED THEN UPDATE SET ... WHEN NOT MATCHED THEN INSERT ...` | ### Pagination | Driver | Pattern | |---|---| | pgx | `LIMIT $1 OFFSET $2` | | mysql | `LIMIT $1 OFFSET $2` | | mssql | `OFFSET $1 ROWS FETCH NEXT $2 ROWS ONLY` | | oracle | `OFFSET $1 ROWS FETCH FIRST $2 ROWS ONLY` | ### Random Ordering | Driver | Pattern | |---|---| | pgx | `ORDER BY random()` | | mysql | `ORDER BY RAND()` | | mssql | `ORDER BY NEWID()` | | oracle | `ORDER BY DBMS_RANDOM.VALUE` | | spanner | `TABLESAMPLE RESERVOIR (N ROWS)` or `ORDER BY FARM_FINGERPRINT(GENERATE_UUID())` | ### Categorical Selection (in SQL) | Driver | Pattern | |---|---| | pgx | `(ARRAY['a','b','c'])[index]` | | mysql | `ELT(index, 'a', 'b', 'c')` | | mssql | `CASE WHEN ... THEN ... END` | | oracle | `DECODE(index, 1, 'a', 2, 'b', 3, 'c')` | ### Cleanup | Driver | Deseed | Drop | |---|---|---| | pgx | `TRUNCATE TABLE t CASCADE` | `DROP TABLE IF EXISTS t` | | mysql | `DELETE FROM t` | `DROP TABLE IF EXISTS t` | | mssql | `DELETE FROM t` | `IF OBJECT_ID('t', 'U') IS NOT NULL DROP TABLE t` | | oracle | `TRUNCATE TABLE t` | `DROP TABLE t CASCADE CONSTRAINTS PURGE` | | spanner | `DELETE FROM t WHERE TRUE` | `DROP TABLE IF EXISTS t` (must drop indexes first) | | mongodb | `{"delete": "t", "deletes": [{"q": {}, "limit": 0}]}` | `{"drop": "t"}` | | cassandra | `TRUNCATE ks.t` | `DROP TABLE IF EXISTS ks.t` | ### Spanner-Specific Notes When migrating configs to Spanner: - **Drop indexes before tables**: Spanner requires all indexes on a table to be dropped before the table itself. Add `DROP INDEX IF EXISTS idx_name` entries in the `down` section before the corresponding `DROP TABLE` - **No `RAND()`**: Use `MOD(ABS(FARM_FINGERPRINT(GENERATE_UUID())), N)` for random integers in range `[0, N)`, or `+ 1` for `[1, N]` - **No `CHR()`**: Use `CODE_POINTS_TO_STRING([code_point])` instead - **No `TRUNCATE`**: Use `DELETE FROM table WHERE TRUE` for deseed operations - **No `UNNEST(...) AS v(col1, col2, ...)`**: Spanner does not support column aliasing on UNNEST. Use `__values__` instead, or `UNNEST(...) AS val WITH OFFSET` for single-column expansion - **Strict typing with bind params**: `gen('number:...')` returns float64, which Spanner rejects for INT64 columns when using bind params (`@pN`). Wrap in `int()`: `int(gen('number:1,100'))` - **String bind params**: If a `ref_rand` value needs to be STRING for Spanner, use `template('%v', value)` to force string type, or use `$1`/`'$1'` inlined placeholders instead of `@pN` - **Use `INSERT OR IGNORE` or `INSERT OR UPDATE`** instead of `ON CONFLICT` ### MongoDB-Specific Notes When migrating SQL configs to MongoDB: - Replace `CREATE TABLE` with `{"create": "collection"}` - Replace `INSERT INTO t (cols) VALUES (...)` with `{"insert": "t", "documents": [{"field": $1, ...}]}` - Replace `SELECT ... FROM t WHERE ...` with `{"find": "t", "filter": {"field": $1}}` - Replace `UPDATE t SET ... WHERE ...` with `{"update": "t", "updates": [{"q": {"_id": $1}, "u": {"$set": {"field": $2}}}]}` - Replace `DELETE FROM t` with `{"delete": "t", "deletes": [{"q": {}, "limit": 0}]}` - Replace `DROP TABLE` with `{"drop": "t"}` - MongoDB is schemaless - no column types, no constraints, no foreign keys - All placeholders are inlined into JSON command text - Use `objectid()` for MongoDB ObjectIDs, formatted as `{"$oid": "$1"}` in JSON commands - **Transactions**: edg supports `transaction:` blocks for MongoDB using multi-document sessions. Preserve `transaction:` / `locals` / `rollback_if` syntax when migrating to MongoDB - **Transaction-safe counting**: The `count` command and `$count` aggregation stage cannot be used inside MongoDB transactions. When migrating SQL `SELECT COUNT(*) ... WHERE condition` inside a transaction, use `$group` with `$cond`: ```json
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub