{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Track changes and revert to previous versions\n", "\n", "Undo mistakes, audit changes, and create point-in-time snapshots of your data." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Problem\n", "\n", "You need to track what changed in your data pipeline, undo accidental modifications, or preserve a specific state for reproducibility." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Solution\n", "\n", "**What's in this recipe:**\n", "\n", "- View version history with `history()` and `get_versions()`\n", "- Access specific versions with `pxt.get_table('table:N')`\n", "- Undo changes with `revert()`\n", "- Create point-in-time snapshots with `pxt.create_snapshot()`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Setup" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:16.222309Z", "iopub.status.busy": "2025-12-12T02:37:16.222161Z", "iopub.status.idle": "2025-12-12T02:37:18.689202Z", "shell.execute_reply": "2025-12-12T02:37:18.688704Z" } }, "outputs": [], "source": [ "%pip install -qU pixeltable" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:18.706807Z", "iopub.status.busy": "2025-12-12T02:37:18.706549Z", "iopub.status.idle": "2025-12-12T02:37:20.034616Z", "shell.execute_reply": "2025-12-12T02:37:20.034340Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Connected to Pixeltable database at: postgresql+psycopg://postgres:@/pixeltable?host=/Users/pjlb/.pixeltable/pgdata\n", "Created directory 'version_demo'.\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pixeltable as pxt\n", "\n", "pxt.drop_dir('version_demo', force=True)\n", "pxt.create_dir('version_demo')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Create a table and make some changes\n", "\n", "Every data or schema change creates a new version." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:20.036493Z", "iopub.status.busy": "2025-12-12T02:37:20.036306Z", "iopub.status.idle": "2025-12-12T02:37:20.105849Z", "shell.execute_reply": "2025-12-12T02:37:20.105485Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created table 'products'.\n" ] } ], "source": [ "# Create table (version 0)\n", "products = pxt.create_table(\n", " 'version_demo/products',\n", " {'name': pxt.String, 'price': pxt.Float, 'category': pxt.String},\n", ")" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:20.107784Z", "iopub.status.busy": "2025-12-12T02:37:20.107641Z", "iopub.status.idle": "2025-12-12T02:37:20.860156Z", "shell.execute_reply": "2025-12-12T02:37:20.859651Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\r", "Inserting rows into `products`: 0 rows [00:00, ? rows/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "Inserting rows into `products`: 3 rows [00:00, 432.95 rows/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "Inserted 3 rows with 0 errors.\n" ] }, { "data": { "text/plain": [ "3 rows inserted, 6 values computed." ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Insert data (version 1)\n", "products.insert(\n", " [\n", " {'name': 'Widget', 'price': 9.99, 'category': 'Tools'},\n", " {'name': 'Gadget', 'price': 24.99, 'category': 'Electronics'},\n", " {'name': 'Gizmo', 'price': 14.99, 'category': 'Electronics'},\n", " ]\n", ")" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:20.862602Z", "iopub.status.busy": "2025-12-12T02:37:20.862123Z", "iopub.status.idle": "2025-12-12T02:37:20.909264Z", "shell.execute_reply": "2025-12-12T02:37:20.908814Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Added 3 column values with 0 errors.\n" ] }, { "data": { "text/plain": [ "3 rows updated, 6 values computed." ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Add a computed column (version 2 - schema change)\n", "products.add_computed_column(price_with_tax=products.price * 1.08)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:20.910990Z", "iopub.status.busy": "2025-12-12T02:37:20.910904Z", "iopub.status.idle": "2025-12-12T02:37:20.933886Z", "shell.execute_reply": "2025-12-12T02:37:20.933431Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\r", "Inserting rows into `products`: 0 rows [00:00, ? rows/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "Inserting rows into `products`: 1 rows [00:00, 297.47 rows/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "data": { "text/plain": [ "1 row updated, 3 values computed." ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Update some data (version 3)\n", "products.update({'price': 19.99}, where=products.name == 'Widget')" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:20.935785Z", "iopub.status.busy": "2025-12-12T02:37:20.935642Z", "iopub.status.idle": "2025-12-12T02:37:20.951221Z", "shell.execute_reply": "2025-12-12T02:37:20.950822Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\r", "Inserting rows into `products`: 0 rows [00:00, ? rows/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "Inserting rows into `products`: 1 rows [00:00, 661.46 rows/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "Inserted 1 row with 0 errors.\n" ] }, { "data": { "text/plain": [ "1 row inserted, 3 values computed." ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Insert more data (version 4)\n", "products.insert(\n", " [{'name': 'Thingamajig', 'price': 49.99, 'category': 'Tools'}]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### View version history\n", "\n", "Use `history()` for a human-readable summary of all changes." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:20.953223Z", "iopub.status.busy": "2025-12-12T02:37:20.952982Z", "iopub.status.idle": "2025-12-12T02:37:20.965677Z", "shell.execute_reply": "2025-12-12T02:37:20.965268Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
versioncreated_atuserchange_typeinsertsupdatesdeleteserrorscomputedschema_change
042025-12-12 02:37:20.941257+00:00Nonedata10003None
132025-12-12 02:37:20.916661+00:00Nonedata01003None
222025-12-12 02:37:20.868057+00:00Noneschema03006Added: price_with_tax
312025-12-12 02:37:20.825297+00:00Nonedata30006None
402025-12-12 02:37:20.044126+00:00Noneschema00000Initial Version
\n", "
" ], "text/plain": [ " version created_at user change_type inserts \\\n", "0 4 2025-12-12 02:37:20.941257+00:00 None data 1 \n", "1 3 2025-12-12 02:37:20.916661+00:00 None data 0 \n", "2 2 2025-12-12 02:37:20.868057+00:00 None schema 0 \n", "3 1 2025-12-12 02:37:20.825297+00:00 None data 3 \n", "4 0 2025-12-12 02:37:20.044126+00:00 None schema 0 \n", "\n", " updates deletes errors computed schema_change \n", "0 0 0 0 3 None \n", "1 1 0 0 3 None \n", "2 3 0 0 6 Added: price_with_tax \n", "3 0 0 0 6 None \n", "4 0 0 0 0 Initial Version " ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# View full history (most recent first)\n", "products.history()" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:20.967774Z", "iopub.status.busy": "2025-12-12T02:37:20.967594Z", "iopub.status.idle": "2025-12-12T02:37:20.977681Z", "shell.execute_reply": "2025-12-12T02:37:20.977289Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
versioncreated_atuserchange_typeinsertsupdatesdeleteserrorscomputedschema_change
042025-12-12 02:37:20.941257+00:00Nonedata10003None
132025-12-12 02:37:20.916661+00:00Nonedata01003None
222025-12-12 02:37:20.868057+00:00Noneschema03006Added: price_with_tax
\n", "
" ], "text/plain": [ " version created_at user change_type inserts \\\n", "0 4 2025-12-12 02:37:20.941257+00:00 None data 1 \n", "1 3 2025-12-12 02:37:20.916661+00:00 None data 0 \n", "2 2 2025-12-12 02:37:20.868057+00:00 None schema 0 \n", "\n", " updates deletes errors computed schema_change \n", "0 0 0 0 3 None \n", "1 1 0 0 3 None \n", "2 3 0 0 6 Added: price_with_tax " ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# View only the last 3 versions\n", "products.history(n=3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Programmatic access to version metadata\n", "\n", "Use `get_versions()` to access version data programmatically." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:20.979648Z", "iopub.status.busy": "2025-12-12T02:37:20.979509Z", "iopub.status.idle": "2025-12-12T02:37:20.988395Z", "shell.execute_reply": "2025-12-12T02:37:20.988072Z" } }, "outputs": [ { "data": { "text/plain": [ "(4, 'data', 1)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Get version metadata as a list of dictionaries\n", "versions = products.get_versions()\n", "\n", "# Access specific version info\n", "latest = versions[0]\n", "latest['version'], latest['change_type'], latest['inserts']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Access a specific version\n", "\n", "Use `pxt.get_table('table_name:version')` to get a read-only handle to a specific version:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:20.990757Z", "iopub.status.busy": "2025-12-12T02:37:20.990618Z", "iopub.status.idle": "2025-12-12T02:37:21.019689Z", "shell.execute_reply": "2025-12-12T02:37:21.019324Z" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
namepricecategory
Gadget24.99Electronics
Gizmo14.99Electronics
Widget9.99Tools
" ], "text/plain": [ " name price category\n", "0 Gadget 24.99 Electronics\n", "1 Gizmo 14.99 Electronics\n", "2 Widget 9.99 Tools" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Get the table at version 1 (after initial insert, before computed column)\n", "products_v1 = pxt.get_table('version_demo/products:1')\n", "\n", "# This is a read-only view of the data at that point in time\n", "products_v1.collect()" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:21.021529Z", "iopub.status.busy": "2025-12-12T02:37:21.021302Z", "iopub.status.idle": "2025-12-12T02:37:21.047620Z", "shell.execute_reply": "2025-12-12T02:37:21.047190Z" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
namepricecategoryprice_with_tax
Gadget24.99Electronics26.989
Gizmo14.99Electronics16.189
Widget9.99Tools10.789
" ], "text/plain": [ " name price category price_with_tax\n", "0 Gadget 24.99 Electronics 26.9892\n", "1 Gizmo 14.99 Electronics 16.1892\n", "2 Widget 9.99 Tools 10.7892" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Compare data at version 2 (after computed column added) vs version 1\n", "# Note: version 1 doesn't have the price_with_tax column yet\n", "products_v2 = pxt.get_table('version_demo/products:2')\n", "products_v2.collect()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Revert to previous version\n", "\n", "Use `revert()` to undo the most recent change. This is irreversible." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:21.049544Z", "iopub.status.busy": "2025-12-12T02:37:21.049408Z", "iopub.status.idle": "2025-12-12T02:37:21.056438Z", "shell.execute_reply": "2025-12-12T02:37:21.055710Z" } }, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Current state: 4 products\n", "products.count()" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:21.058803Z", "iopub.status.busy": "2025-12-12T02:37:21.058657Z", "iopub.status.idle": "2025-12-12T02:37:21.086360Z", "shell.execute_reply": "2025-12-12T02:37:21.085961Z" } }, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Revert the last insert (removes Thingamajig)\n", "products.revert()\n", "products.count()" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:21.088574Z", "iopub.status.busy": "2025-12-12T02:37:21.088352Z", "iopub.status.idle": "2025-12-12T02:37:21.098746Z", "shell.execute_reply": "2025-12-12T02:37:21.098294Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
versioncreated_atuserchange_typeinsertsupdatesdeleteserrorscomputedschema_change
032025-12-12 02:37:20.916661+00:00Nonedata01003None
122025-12-12 02:37:20.868057+00:00Noneschema03006Added: price_with_tax
212025-12-12 02:37:20.825297+00:00Nonedata30006None
302025-12-12 02:37:20.044126+00:00Noneschema00000Initial Version
\n", "
" ], "text/plain": [ " version created_at user change_type inserts \\\n", "0 3 2025-12-12 02:37:20.916661+00:00 None data 0 \n", "1 2 2025-12-12 02:37:20.868057+00:00 None schema 0 \n", "2 1 2025-12-12 02:37:20.825297+00:00 None data 3 \n", "3 0 2025-12-12 02:37:20.044126+00:00 None schema 0 \n", "\n", " updates deletes errors computed schema_change \n", "0 1 0 0 3 None \n", "1 3 0 0 6 Added: price_with_tax \n", "2 0 0 0 6 None \n", "3 0 0 0 0 Initial Version " ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# History now shows version 4 was reverted\n", "products.history()" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:21.100654Z", "iopub.status.busy": "2025-12-12T02:37:21.100491Z", "iopub.status.idle": "2025-12-12T02:37:21.141627Z", "shell.execute_reply": "2025-12-12T02:37:21.141262Z" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
nameprice
Widget9.99
" ], "text/plain": [ " name price\n", "0 Widget 9.99" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Can revert multiple times (back to before the update)\n", "products.revert()\n", "\n", "# Check the Widget price is back to original\n", "products.where(products.name == 'Widget').select(\n", " products.name, products.price\n", ").collect()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Create point-in-time snapshots\n", "\n", "Snapshots freeze a table's state for reproducibility. Unlike `revert()`, snapshots preserve the data indefinitely." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:21.143834Z", "iopub.status.busy": "2025-12-12T02:37:21.143555Z", "iopub.status.idle": "2025-12-12T02:37:21.164413Z", "shell.execute_reply": "2025-12-12T02:37:21.163974Z" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
namepricecategoryprice_with_tax
Gadget24.99Electronics26.989
Gizmo14.99Electronics16.189
Widget9.99Tools10.789
" ], "text/plain": [ " name price category price_with_tax\n", "0 Gadget 24.99 Electronics 26.9892\n", "1 Gizmo 14.99 Electronics 16.1892\n", "2 Widget 9.99 Tools 10.7892" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Create a snapshot of the current state\n", "snapshot_v1 = pxt.create_snapshot('version_demo/products_v1', products)\n", "\n", "snapshot_v1.collect()" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:21.166488Z", "iopub.status.busy": "2025-12-12T02:37:21.166350Z", "iopub.status.idle": "2025-12-12T02:37:21.203892Z", "shell.execute_reply": "2025-12-12T02:37:21.203451Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\r", "Inserting rows into `products`: 0 rows [00:00, ? rows/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "Inserting rows into `products`: 1 rows [00:00, 535.67 rows/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "Inserted 1 row with 0 errors.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "Inserting rows into `products`: 0 rows [00:00, ? rows/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "Inserting rows into `products`: 1 rows [00:00, 558.05 rows/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
namepricecategoryprice_with_tax
Gizmo14.99Electronics16.189
Widget9.99Tools10.789
Doohickey99.99Premium107.989
Gadget29.99Electronics32.389
" ], "text/plain": [ " name price category price_with_tax\n", "0 Gizmo 14.99 Electronics 16.1892\n", "1 Widget 9.99 Tools 10.7892\n", "2 Doohickey 99.99 Premium 107.9892\n", "3 Gadget 29.99 Electronics 32.3892" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Now make changes to the original table\n", "products.insert(\n", " [{'name': 'Doohickey', 'price': 99.99, 'category': 'Premium'}]\n", ")\n", "products.update({'price': 29.99}, where=products.name == 'Gadget')\n", "\n", "products.collect()" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "execution": { "iopub.execute_input": "2025-12-12T02:37:21.206066Z", "iopub.status.busy": "2025-12-12T02:37:21.205708Z", "iopub.status.idle": "2025-12-12T02:37:21.213296Z", "shell.execute_reply": "2025-12-12T02:37:21.212920Z" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
namepricecategoryprice_with_tax
Gizmo14.99Electronics16.189
Widget9.99Tools10.789
Gadget24.99Electronics26.989
" ], "text/plain": [ " name price category price_with_tax\n", "0 Gizmo 14.99 Electronics 16.1892\n", "1 Widget 9.99 Tools 10.7892\n", "2 Gadget 24.99 Electronics 26.9892" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Snapshot remains unchanged - still shows original data\n", "snapshot_v1.collect()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Explanation\n", "\n", "**What creates a new version:**\n", "\n", "- `insert()` - adding rows\n", "- `update()` - modifying rows\n", "- `delete()` - removing rows\n", "- `add_column()` / `add_computed_column()` - schema changes\n", "- `drop_column()` - schema changes\n", "- `rename_column()` - schema changes\n", "\n", "**Version history methods:**\n", "\n", "- `history()` - Human-readable DataFrame showing all changes\n", "- `get_versions()` - List of dictionaries for programmatic access\n", "\n", "**Accessing specific versions:**\n", "\n", "- `pxt.get_table('table_name:N')` - Get read-only handle to version N\n", "- Useful for comparing data across versions, auditing changes, or recovering specific values\n", "- Version handles are read-only—you cannot modify historical versions\n", "\n", "**Reverting:**\n", "\n", "- `revert()` undoes the most recent version\n", "- Can call multiple times to go back further\n", "- Cannot revert past version 0\n", "- Cannot revert if a snapshot references that version\n", "\n", "**Snapshots vs revert:**\n", "\n", "- Snapshots are persistent, named, point-in-time copies\n", "- `revert()` permanently removes the latest version\n", "- Use snapshots when you need to preserve state for reproducibility\n", "- Use `revert()` to undo mistakes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## See also\n", "\n", "- [Data sharing](/platform/data-sharing) - Share tables between environments\n", "- [Iterative development](https://docs.pixeltable.com/howto/cookbooks/core/dev-iterative-workflow) - Fast feedback during development" ] } ], "metadata": { "kernelspec": { "display_name": "pixeltable", "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.10.18" } }, "nbformat": 4, "nbformat_minor": 2 }