{ "cells": [ { "cell_type": "markdown", "id": "6d47d2f0", "metadata": {}, "source": [ "# Notebook 1 - in-memory and single-file conversion\n", "\n", "This walkthrough mirrors `examples/01_convert_string.py` and `examples/02_convert_file.py`. It validates the core conversion contract: BigQuery DDL metadata moves into Dataform `config {}` blocks, downstream reads of tables produced in the same migration become `${ref(...)}` calls, and DML that cannot be proven safe remains an `operations` action for review.\n" ] }, { "cell_type": "code", "execution_count": 1, "id": "9e5c0ca4", "metadata": { "execution": { "iopub.execute_input": "2026-07-12T14:42:53.311420Z", "iopub.status.busy": "2026-07-12T14:42:53.311152Z", "iopub.status.idle": "2026-07-12T14:42:54.151537Z", "shell.execute_reply": "2026-07-12T14:42:54.150285Z" } }, "outputs": [], "source": [ "from pathlib import Path\n", "\n", "import matplotlib.pyplot as plt\n", "\n", "from sql2sqlx import convert_file, convert_string\n", "\n", "ROOT = next(\n", " path for path in [Path.cwd(), *Path.cwd().parents] if (path / \"pyproject.toml\").exists()\n", ")\n", "EXAMPLES = ROOT / \"examples\"\n", "assert EXAMPLES.is_dir(), EXAMPLES" ] }, { "cell_type": "markdown", "id": "ea3ac2ed", "metadata": {}, "source": [ "## Convert an in-memory pipeline\n", "\n", "The input has two statements. The CTAS is safe to lift into a Dataform table action because its target, query body, partitioning expression, and option metadata are all explicit in the SQL. The `INSERT` is preserved as `operations` by the default strategy because append semantics often need human confirmation before becoming an incremental model.\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "9f8cc1b8", "metadata": { "execution": { "iopub.execute_input": "2026-07-12T14:42:54.156284Z", "iopub.status.busy": "2026-07-12T14:42:54.155759Z", "iopub.status.idle": "2026-07-12T14:42:54.168773Z", "shell.execute_reply": "2026-07-12T14:42:54.166026Z" } }, "outputs": [ { "data": { "text/plain": [ "[('daily_orders.sqlx', 'table', 'daily_orders'),\n", " ('order_history_insert.sqlx', 'operations', 'order_history_insert')]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sql = \"\"\"\n", "CREATE OR REPLACE TABLE analytics.daily_orders\n", "PARTITION BY DATE(order_ts)\n", "OPTIONS(description = \"Daily order rollup\")\n", "AS\n", "SELECT DATE(order_ts) AS d, COUNT(*) AS n\n", "FROM raw.orders\n", "GROUP BY 1;\n", "\n", "INSERT INTO analytics.order_history (d, n)\n", "SELECT d, n FROM analytics.daily_orders;\n", "\"\"\"\n", "\n", "result = convert_string(sql, name=\"pipeline.sql\")\n", "[(file.relpath, file.action_type.value, file.action_name) for file in result.files]" ] }, { "cell_type": "markdown", "id": "98270276", "metadata": {}, "source": [ "## Inspect the emitted SQLX\n", "\n", "Review the generated files exactly as they would be written to `definitions/`. The table action contains Dataform metadata and a pure `SELECT`; the operations action keeps the `INSERT` statement but rewrites the read of `analytics.daily_orders` to the generated action name.\n" ] }, { "cell_type": "code", "execution_count": 3, "id": "0f44add9", "metadata": { "execution": { "iopub.execute_input": "2026-07-12T14:42:54.171736Z", "iopub.status.busy": "2026-07-12T14:42:54.171446Z", "iopub.status.idle": "2026-07-12T14:42:54.176312Z", "shell.execute_reply": "2026-07-12T14:42:54.175323Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "===== daily_orders.sqlx (table) =====\n", "config {\n", " type: \"table\",\n", " schema: \"analytics\",\n", " name: \"daily_orders\",\n", " description: \"Daily order rollup\",\n", " bigquery: {\n", " partitionBy: \"DATE(order_ts)\"\n", " }\n", "}\n", "\n", "-- source: pipeline.sql:2 (CREATE TABLE converted by sql2sqlx v0.1.0)\n", "SELECT DATE(order_ts) AS d, COUNT(*) AS n\n", "FROM raw.orders\n", "GROUP BY 1\n", "\n", "\n", "===== order_history_insert.sqlx (operations) =====\n", "config {\n", " type: \"operations\",\n", " name: \"order_history_insert\"\n", "}\n", "\n", "-- source: pipeline.sql:10 (INSERT converted by sql2sqlx v0.1.0)\n", "INSERT INTO analytics.order_history (d, n)\n", "SELECT d, n FROM ${ref(\"analytics\", \"daily_orders\")}\n", "\n", "\n" ] } ], "source": [ "for file in result.files:\n", " print(f\"===== {file.relpath} ({file.action_type.value}) =====\")\n", " print(file.content)\n", " print()" ] }, { "cell_type": "markdown", "id": "239f5dff", "metadata": {}, "source": [ "## Validate conversion invariants\n", "\n", "These assertions make the notebook executable documentation. If converter behavior changes, the notebook fails instead of silently publishing stale output.\n" ] }, { "cell_type": "code", "execution_count": 4, "id": "84928040", "metadata": { "execution": { "iopub.execute_input": "2026-07-12T14:42:54.178753Z", "iopub.status.busy": "2026-07-12T14:42:54.178462Z", "iopub.status.idle": "2026-07-12T14:42:54.186540Z", "shell.execute_reply": "2026-07-12T14:42:54.185482Z" } }, "outputs": [ { "data": { "text/plain": [ "{'actions': {'table': 1, 'operations': 1}, 'refs_rewritten': 1, 'warnings': []}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "table = next(file for file in result.files if file.action_name == \"daily_orders\")\n", "insert = next(file for file in result.files if file.action_name == \"order_history_insert\")\n", "\n", "assert table.action_type.value == \"table\"\n", "assert 'type: \"table\"' in table.content\n", "assert 'schema: \"analytics\"' in table.content\n", "assert 'partitionBy: \"DATE(order_ts)\"' in table.content\n", "assert 'description: \"Daily order rollup\"' in table.content\n", "assert insert.action_type.value == \"operations\"\n", "assert '${ref(\"analytics\", \"daily_orders\")}' in insert.content\n", "assert result.report.refs_rewritten == 1\n", "\n", "{\n", " \"actions\": result.report.actions_by_type,\n", " \"refs_rewritten\": result.report.refs_rewritten,\n", " \"warnings\": [warning.code for warning in result.report.warnings],\n", "}" ] }, { "cell_type": "markdown", "id": "5782d65d", "metadata": {}, "source": [ "## Convert one repository SQL file\n", "\n", "`convert_file` reads a `.sql` file from disk and returns the same in-memory result object used by `convert_string`. The staged-orders example includes partitioning, clustering, labels, and an upstream raw table reference.\n" ] }, { "cell_type": "code", "execution_count": 5, "id": "16bc398d", "metadata": { "execution": { "iopub.execute_input": "2026-07-12T14:42:54.188919Z", "iopub.status.busy": "2026-07-12T14:42:54.188652Z", "iopub.status.idle": "2026-07-12T14:42:54.195093Z", "shell.execute_reply": "2026-07-12T14:42:54.194247Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "config {\n", " type: \"table\",\n", " schema: \"staging\",\n", " name: \"orders\",\n", " description: \"One row per order event\",\n", " bigquery: {\n", " partitionBy: \"DATE(ts)\",\n", " clusterBy: [\"customer_id\"],\n", " labels: {\n", " layer: \"staging\",\n", " owner: \"data-eng\"\n", " },\n", " partitionExpirationDays: 365,\n", " requirePartitionFilter: true\n", " }\n", "}\n", "\n", "-- source: stg_orders.sql:2 (CREATE TABLE converted by sql2sqlx v0.1.0)\n", "-- Orders staged from the raw event stream.\n", "SELECT\n", " event_id AS order_id,\n", " customer_id,\n", " amount,\n", " ts\n", "FROM raw.events\n", "WHERE event_type = 'order'\n", "\n", "report: {'files_read': 1, 'statements': 1, 'actions_by_type': {'table': 1}, 'refs_rewritten': 0, 'refs_unresolved': ['raw.events'], 'warnings': [], 'failures': {}, 'elapsed_seconds': 0.001, 'input_bytes': 419}\n" ] } ], "source": [ "single_file = EXAMPLES / \"sql\" / \"staging\" / \"stg_orders.sql\"\n", "file_result = convert_file(str(single_file))\n", "file_sqlx = file_result.files[0]\n", "print(file_sqlx.content)\n", "print(\"report:\", file_result.report.to_dict())" ] }, { "cell_type": "markdown", "id": "4085f79b", "metadata": {}, "source": [ "## Visualize action counts\n", "\n", "Small charts are useful in migration reviews because they show at a glance whether a batch produced the expected mix of tables, views, incrementals, and operations.\n" ] }, { "cell_type": "code", "execution_count": 6, "id": "48bec0bd", "metadata": { "execution": { "iopub.execute_input": "2026-07-12T14:42:54.198028Z", "iopub.status.busy": "2026-07-12T14:42:54.197766Z", "iopub.status.idle": "2026-07-12T14:42:54.368751Z", "shell.execute_reply": "2026-07-12T14:42:54.367514Z" } }, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "counts = result.report.actions_by_type\n", "fig, ax = plt.subplots(figsize=(6, 3))\n", "ax.bar(counts.keys(), counts.values(), color=\"#4E79A7\")\n", "ax.set_title(\"Actions emitted from in-memory SQL\")\n", "ax.set_ylabel(\"files\")\n", "ax.set_xlabel(\"Dataform action type\")\n", "plt.show()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.13" } }, "nbformat": 4, "nbformat_minor": 5 }