diff --git a/docs/cli.rst b/docs/cli.rst index da6a562..8b33206 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -761,6 +761,8 @@ You can delete all the existing rows in the table before inserting the new recor $ sqlite-utils insert dogs.db dogs dogs.json --truncate +You can add the ``--analyze`` option to run ``ANALYZE`` against the table after the rows have been inserted. + .. _cli_inserting_data_binary: Inserting binary data @@ -1697,6 +1699,8 @@ This will create an index on that table on ``(col1, col2 desc, col3)``. If your column names are already prefixed with a hyphen you'll need to manually execute a ``CREATE INDEX`` SQL statement to add indexes to them rather than using this tool. +Add the ``--analyze`` option to run ``ANALYZE`` against the index after it has been created. + .. _cli_fts: Configuring full-text search @@ -1817,6 +1821,8 @@ You can run it against specific tables, or against specific named indexes, by pa $ sqlite-utils analyze mydb.db mytable idx_mytable_name +You can also run ``ANALYZE`` as part of another command using the ``--analyze`` option. This is supported by the ``create-index``, ``insert`` and ``upsert`` commands. + .. _cli_vacuum: Vacuum diff --git a/sqlite_utils/cli.py b/sqlite_utils/cli.py index cbc091c..187795b 100644 --- a/sqlite_utils/cli.py +++ b/sqlite_utils/cli.py @@ -490,8 +490,15 @@ def index_foreign_keys(path, load_extension): default=False, is_flag=True, ) +@click.option( + "--analyze", + help="Run ANALYZE after creating the index", + is_flag=True, +) @load_extension_option -def create_index(path, table, column, name, unique, if_not_exists, load_extension): +def create_index( + path, table, column, name, unique, if_not_exists, analyze, load_extension +): """ Add an index to the specified table covering the specified columns. Use "sqlite-utils create-index mydb -- -column" to specify descending @@ -506,7 +513,11 @@ def create_index(path, table, column, name, unique, if_not_exists, load_extensio col = DescIndex(col[1:]) columns.append(col) db[table].create_index( - columns, index_name=name, unique=unique, if_not_exists=if_not_exists + columns, + index_name=name, + unique=unique, + if_not_exists=if_not_exists, + analyze=analyze, ) @@ -726,6 +737,11 @@ def insert_upsert_options(fn): envvar="SQLITE_UTILS_DETECT_TYPES", help="Detect types for columns in CSV/TSV data", ), + click.option( + "--analyze", + is_flag=True, + help="Run ANALYZE at the end of this operation", + ), load_extension_option, click.option("--silent", is_flag=True, help="Do not show progress bar"), ) @@ -761,6 +777,7 @@ def insert_upsert_implementation( default=None, encoding=None, detect_types=None, + analyze=False, load_extension=None, silent=False, ): @@ -853,7 +870,12 @@ def insert_upsert_implementation( else: docs = (fn(doc) or doc for doc in docs) - extra_kwargs = {"ignore": ignore, "replace": replace, "truncate": truncate} + extra_kwargs = { + "ignore": ignore, + "replace": replace, + "truncate": truncate, + "analyze": analyze, + } if not_null: extra_kwargs["not_null"] = set(not_null) if default: @@ -950,6 +972,7 @@ def insert( alter, encoding, detect_types, + analyze, load_extension, silent, ignore, @@ -1005,6 +1028,7 @@ def insert( truncate=truncate, encoding=encoding, detect_types=detect_types, + analyze=analyze, load_extension=load_extension, silent=silent, not_null=not_null, @@ -1039,6 +1063,7 @@ def upsert( default, encoding, detect_types, + analyze, load_extension, silent, ): @@ -1072,6 +1097,7 @@ def upsert( default=default, encoding=encoding, detect_types=detect_types, + analyze=analyze, load_extension=load_extension, silent=silent, ) diff --git a/tests/test_cli.py b/tests/test_cli.py index b4163c4..5f095a6 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -224,6 +224,17 @@ def test_create_index(db_path): ) +def test_create_index_analyze(db_path): + db = Database(db_path) + assert "sqlite_stat1" not in db.table_names() + assert [] == db["Gosh"].indexes + result = CliRunner().invoke( + cli.cli, ["create-index", db_path, "Gosh", "c1", "--analyze"] + ) + assert result.exit_code == 0 + assert "sqlite_stat1" in db.table_names() + + def test_create_index_desc(db_path): db = Database(db_path) assert [] == db["Gosh"].indexes @@ -889,6 +900,20 @@ def test_upsert(db_path, tmpdir): ] +def test_upsert_analyze(db_path, tmpdir): + db = Database(db_path) + db["rows"].insert({"id": 1, "foo": "x", "n": 3}, pk="id") + db["rows"].create_index(["n"]) + assert "sqlite_stat1" not in db.table_names() + result = CliRunner().invoke( + cli.cli, + ["upsert", db_path, "rows", "-", "--nl", "--analyze", "--pk", "id"], + input='{"id": 2, "foo": "bar", "n": 1}', + ) + assert 0 == result.exit_code, result.output + assert "sqlite_stat1" in db.table_names() + + def test_upsert_flatten(tmpdir): db_path = str(tmpdir / "flat.db") db = Database(db_path) diff --git a/tests/test_cli_insert.py b/tests/test_cli_insert.py index efa55bd..0d6b482 100644 --- a/tests/test_cli_insert.py +++ b/tests/test_cli_insert.py @@ -327,6 +327,20 @@ def test_insert_alter(db_path, tmpdir): ] == list(db.query("select foo, n, baz from from_json_nl")) +def test_insert_analyze(db_path): + db = Database(db_path) + db["rows"].insert({"foo": "x", "n": 3}) + db["rows"].create_index(["n"]) + assert "sqlite_stat1" not in db.table_names() + result = CliRunner().invoke( + cli.cli, + ["insert", db_path, "rows", "-", "--nl", "--analyze"], + input='{"foo": "bar", "n": 1}\n{"foo": "baz", "n": 2}', + ) + assert 0 == result.exit_code, result.output + assert "sqlite_stat1" in db.table_names() + + def test_insert_lines(db_path): result = CliRunner().invoke( cli.cli,