diff --git a/docs/cli.rst b/docs/cli.rst index 95e22fd..806b416 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -221,6 +221,17 @@ After running the above ``dogs.json`` example, try running this:: This will replace the record for id=2 (Pancakes) with a new record with an updated age. +.. _cli_add_column: + +Adding columns +============== + +You can add a column using the ``add-column`` command:: + + $ sqlite-utils add-column mydb.db mytable nameofcolumn text + +The last argument here is the type of the column to be created. You can use one of ``text``, ``integer``, ``float`` or ``blob``. + .. _cli_create_index: Creating indexes diff --git a/sqlite_utils/cli.py b/sqlite_utils/cli.py index cfc9676..7b7501a 100644 --- a/sqlite_utils/cli.py +++ b/sqlite_utils/cli.py @@ -134,6 +134,26 @@ def optimize(path, no_vacuum): db.vacuum() +@cli.command(name="add-column") +@click.argument( + "path", + type=click.Path(exists=True, file_okay=True, dir_okay=False, allow_dash=False), + required=True, +) +@click.argument("table") +@click.argument("col_name") +@click.argument( + "col_type", + type=click.Choice( + ["integer", "float", "blob", "text", "INTEGER", "FLOAT", "BLOB", "TEXT"] + ), +) +def add_column(path, table, col_name, col_type): + "Add a column to the specified table" + db = sqlite_utils.Database(path) + db[table].add_column(col_name, col_type) + + @cli.command(name="create-index") @click.argument( "path", diff --git a/tests/test_cli.py b/tests/test_cli.py index 73015a3..6791fcb 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -6,6 +6,8 @@ import os import pytest import sqlite3 +from .utils import collapse_whitespace + CREATE_TABLES = """ create table Gosh (c1 text, c2 text, c3 text); @@ -170,6 +172,44 @@ def test_create_index(db_path): ) +@pytest.mark.parametrize( + "col_name,col_type,expected_schema", + ( + ("text", "TEXT", "CREATE TABLE [dogs] ( [name] TEXT , [text] TEXT)"), + ( + "integer", + "INTEGER", + "CREATE TABLE [dogs] ( [name] TEXT , [integer] INTEGER)", + ), + ("float", "FLOAT", "CREATE TABLE [dogs] ( [name] TEXT , [float] FLOAT)"), + ("blob", "blob", "CREATE TABLE [dogs] ( [name] TEXT , [blob] BLOB)"), + ), +) +def test_add_column(db_path, col_name, col_type, expected_schema): + db = Database(db_path) + db.create_table("dogs", {"name": str}) + assert "CREATE TABLE [dogs] ( [name] TEXT )" == collapse_whitespace( + db["dogs"].schema + ) + assert ( + 0 + == CliRunner() + .invoke(cli.cli, ["add-column", db_path, "dogs", col_name, col_type]) + .exit_code + ) + assert expected_schema == collapse_whitespace(db["dogs"].schema) + + +def test_add_column_error_invalid_type(db_path): + db = Database(db_path) + db.create_table("dogs", {"name": str}) + result = CliRunner().invoke( + cli.cli, ["add-column", db_path, "dogs", "blah", "badtype"] + ) + assert 0 != result.exit_code + assert 'Invalid value for "col_type"' in result.output + + def test_enable_fts(db_path): assert None == Database(db_path)["Gosh"].detect_fts() result = CliRunner().invoke( diff --git a/tests/test_create.py b/tests/test_create.py index aae4817..29618dc 100644 --- a/tests/test_create.py +++ b/tests/test_create.py @@ -4,9 +4,10 @@ import datetime import json import pathlib import pytest -import re import sqlite3 +from .utils import collapse_whitespace + try: import pandas as pd except ImportError: @@ -364,10 +365,3 @@ def test_create_table_numpy(fresh_db): "np.uint8": 8, } ] == list(fresh_db["types"].rows) - - -COLLAPSE_RE = re.compile("\s+") - - -def collapse_whitespace(s): - return COLLAPSE_RE.sub(" ", s) diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 0000000..1e3d968 --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,7 @@ +import re + +COLLAPSE_RE = re.compile(r"\s+") + + +def collapse_whitespace(s): + return COLLAPSE_RE.sub(" ", s)