From 2fed87da6ea990d295672e4db2c8ae97b787913e Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 12 Jun 2019 18:35:02 -0700 Subject: [PATCH] --not-null-default and not_null_default=, refs #24 --- docs/cli.rst | 4 ++++ docs/python-api.rst | 6 ++++++ sqlite_utils/cli.py | 23 +++++++++++++++++++---- sqlite_utils/db.py | 15 +++++++++++++-- tests/.DS_Store | Bin 0 -> 6148 bytes tests/test_cli.py | 21 +++++++++++++++++++++ tests/test_create.py | 34 ++++++++++++++++++++++++---------- 7 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 tests/.DS_Store diff --git a/docs/cli.rst b/docs/cli.rst index 4ef6584..27994ba 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -280,6 +280,10 @@ You can explicitly specify the column you wish to reference using ``--fk-col``:: $ sqlite-utils add-column mydb.db dogs species_id --fk species --fk-col ref +You can set a ``NOT NULL DEFAULT 'x'`` constraint on the new column using ``--not-null-default``:: + + $ sqlite-utils add-column mydb.db dogs friends_count integer --not-null-default 0 + .. _cli_add_column_alter: Adding columns automatically on insert/update diff --git a/docs/python-api.rst b/docs/python-api.rst index 331a84e..41f13d8 100644 --- a/docs/python-api.rst +++ b/docs/python-api.rst @@ -284,6 +284,12 @@ You can explicitly specify the column you wish to reference using ``fk_col``: db["dogs"].add_column("species_id", fk="species", fk_col="ref") +You can set a ``NOT NULL DEFAULT 'x'`` constraint on the new column using ``not_null_default``: + +.. code-block:: python + + db["dogs"].add_column("friends_count", int, not_null_default=0) + .. _python_api_add_column_alter: Adding columns automatically on insert/update diff --git a/sqlite_utils/cli.py b/sqlite_utils/cli.py index daf4abc..4a32ddb 100644 --- a/sqlite_utils/cli.py +++ b/sqlite_utils/cli.py @@ -169,12 +169,27 @@ def optimize(path, no_vacuum): ), required=False, ) -@click.option("--fk", type=str, required=False) -@click.option("--fk-col", type=str, required=False) -def add_column(path, table, col_name, col_type, fk, fk_col): +@click.option( + "--fk", type=str, required=False, help="Table to reference as a foreign key" +) +@click.option( + "--fk-col", + type=str, + required=False, + help="Referenced column on that foreign key table - if omitted will automatically use the primary key", +) +@click.option( + "--not-null-default", + type=str, + required=False, + help="Add NOT NULL DEFAULT 'TEXT' constraint", +) +def add_column(path, table, col_name, col_type, fk, fk_col, not_null_default): "Add a column to the specified table" db = sqlite_utils.Database(path) - db[table].add_column(col_name, col_type, fk=fk, fk_col=fk_col) + db[table].add_column( + col_name, col_type, fk=fk, fk_col=fk_col, not_null_default=not_null_default + ) @cli.command(name="add-foreign-key") diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index 07701bd..a77d9da 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -292,7 +292,9 @@ class Table: self.db.conn.execute(sql) return self - def add_column(self, col_name, col_type=None, fk=None, fk_col=None): + def add_column( + self, col_name, col_type=None, fk=None, fk_col=None, not_null_default=None + ): fk_col_type = None if fk is not None: # fk must be a valid table @@ -313,10 +315,19 @@ class Table: fk_col_type = "INTEGER" if col_type is None: col_type = str - sql = "ALTER TABLE [{table}] ADD COLUMN [{col_name}] {col_type};".format( + not_null_sql = None + if not_null_default is not None: + not_null_sql = "NOT NULL DEFAULT {}".format( + # Use SQLite itself to correctly escape this string: + self.db.conn.execute( + "SELECT quote(:default)", {"default": not_null_default} + ).fetchone()[0] + ) + sql = "ALTER TABLE [{table}] ADD COLUMN [{col_name}] {col_type}{not_null_default};".format( table=self.name, col_name=col_name, col_type=fk_col_type or COLUMN_TYPE_MAPPING[col_type], + not_null_default=(" " + not_null_sql) if not_null_sql else "", ) self.db.conn.execute(sql) if fk is not None: diff --git a/tests/.DS_Store b/tests/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0