diff --git a/docs/cli.rst b/docs/cli.rst index 2c7b5f3..5281d02 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -13,10 +13,14 @@ Running queries and returning JSON You can execute a SQL query against a database and get the results back as JSON like this:: - $ sqlite-utils dogs.db "select * from dogs" + $ sqlite-utils query dogs.db "select * from dogs" [{"id": 1, "age": 4, "name": "Cleo"}, {"id": 2, "age": 2, "name": "Pancakes"}] +This is the default subcommand for ``sqlite-utils``, so you can instead use this:: + + $ sqlite-utils dogs.db "select * from dogs" + Use ``--nl`` to get back newline-delimited JSON objects:: $ sqlite-utils dogs.db "select * from dogs" --nl @@ -69,6 +73,19 @@ This will default to including the column names as a header row. To exclude the 1,4,Cleo 2,2,Pancakes +.. _cli_rows: + +Returning all rows in a table +============================= + +You can return every row in a specified table using the ``rows`` subcommand:: + + $ sqlite-utils rows dogs.db dogs + [{"id": 1, "age": 4, "name": "Cleo"}, + {"id": 2, "age": 2, "name": "Pancakes"}] + +This command accepts the same output options as ``query`` - so you can pass ``--nl``, ``--csv`` and ``--no-headers``. + Listing tables ============== diff --git a/sqlite_utils/cli.py b/sqlite_utils/cli.py index e44d36f..568f3eb 100644 --- a/sqlite_utils/cli.py +++ b/sqlite_utils/cli.py @@ -208,13 +208,6 @@ def upsert(path, table, json_file, pk, nl, csv, batch_size): ) @click.argument("sql") @output_options -@click.option("--nl", help="Output newline-delimited JSON", is_flag=True, default=False) -@click.option( - "--arrays", - help="Output rows as arrays instead of objects", - is_flag=True, - default=False, -) def query(path, sql, nl, arrays, csv, no_headers): "Execute SQL query and return the results as JSON" db = sqlite_utils.Database(path) @@ -231,6 +224,28 @@ def query(path, sql, nl, arrays, csv, no_headers): click.echo(line) +@cli.command() +@click.argument( + "path", + type=click.Path(file_okay=True, dir_okay=False, allow_dash=False), + required=True, +) +@click.argument("table") +@output_options +@click.pass_context +def rows(ctx, path, table, nl, arrays, csv, no_headers): + "Output all rows in the specified table" + ctx.invoke( + query, + path=path, + sql="select * from [{}]".format(table), + nl=nl, + arrays=arrays, + csv=csv, + no_headers=no_headers, + ) + + def output_rows(iterator, headers, nl, arrays): # We have to iterate two-at-a-time so we can know if we # should output a trailing comma or if we have reached diff --git a/tests/test_cli.py b/tests/test_cli.py index 41c427c..8ca35fb 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -236,3 +236,32 @@ def test_query_json(db_path, sql, args, expected): ) result = CliRunner().invoke(cli.cli, [db_path, sql] + args) assert expected == result.output.strip() + + +@pytest.mark.parametrize( + "args,expected", + [ + ( + [], + '[{"id": 1, "name": "Cleo", "age": 4},\n {"id": 2, "name": "Pancakes", "age": 2}]', + ), + ( + ["--nl"], + '{"id": 1, "name": "Cleo", "age": 4}\n{"id": 2, "name": "Pancakes", "age": 2}', + ), + (["--arrays"], '[[1, "Cleo", 4],\n [2, "Pancakes", 2]]'), + (["--arrays", "--nl"], '[1, "Cleo", 4]\n[2, "Pancakes", 2]'), + ], +) +def test_rows(db_path, args, expected): + db = Database(db_path) + with db.conn: + db["dogs"].insert_all( + [ + {"id": 1, "age": 4, "name": "Cleo"}, + {"id": 2, "age": 2, "name": "Pancakes"}, + ], + column_order=("id", "name", "age"), + ) + result = CliRunner().invoke(cli.cli, ["rows", db_path, "dogs"] + args) + assert expected == result.output.strip()