.. _usage: ===== Usage ===== Shillelagh implements the `Python DB API 2.0 `_ specification and a custom `SQLAlchemy `_ dialect. It also comes with a simple command-line utility to run queries from the console. .. _dbapi2: DB API 2.0 ========== The DB API 2.0 specification defines standard mechanisms to create database connections and to work with cursors. Here's a simple example that creates a table, inserts some data, and queries it: .. code-block:: python from shillelagh.backends.apsw.db import connect connection = connect(":memory:") cursor = connection.cursor() query = "CREATE TABLE a_table (A int, B string)" cursor.execute(query) query = "INSERT INTO a_table VALUES (?, ?)" cursor.execute(query, (1, "one")) cursor.execute(query, (2, "two")) query = "SELECT * FROM a_table" for row in cursor.execute(query): print(row) You can use a file instead of ``:memory:``: .. code-block:: python from shillelagh.backends.apsw.db import connect connection = connect("/path/to/file.sqlite") Note that using a file is not recommended for security reasons. Shillelagh works by creating `virtual tables `_, and if a given resource requires credentials for access they will be stored in the table name. Configuration ~~~~~~~~~~~~~ By default all available adapters are loaded by Shillelagh. It's possible to limit the adapters that you want to load by passing a list of strings to the ``adapters`` argument when creating the connection: .. code-block:: python from shillelagh.adapters.registry import registry from shillelagh.backends.apsw.db import connect # show names of available adapters print(registry.loaders.keys()) # enable on the CSV and the WeatherAPI adapters connection = connect(":memory:", adapters=["csvfile", "weatherapi"]) Some adapters allow optional configuration to be passed via keyword arguments. For example, we can specify an API key for WeatherAPI: .. code-block:: python from shillelagh.backends.apsw.db import connect connection = connect(":memory:", adapter_kwargs={"weatherapi": {"api_key": "XXX"}}) You can find the accepted arguments in the documentation of each one the :ref:`adapters`. When loading adapters, you can also specify the ``safe`` keyword. When set to true, this will ensure that only "safe" adapters are loaded — ie, adapters that have no access to the filesystem. The keyword also ensures that an exception is raised whenever there are repeated adapters with the same name, to prevent a malicious party from introducing an adapter with the same name as an authorized one: .. code-block:: python from shillelagh.adapters.registry import registry from shillelagh.adapters.file.csvfile import CSVFile from shillelagh.backends.apsw.db import connect registry.add('csvfile', CSVFile) registry.add('csvfile', FakeAdapter) connect(':memory:', adapters=['csvfile'], safe=True) The code above will raise an exception saying "Multiple adapters found with name csvfile". This is needed because adapters can be loaded from third-party libraries via `entry points `_, and not just from the Shillelagh library. Registering new adapters ~~~~~~~~~~~~~~~~~~~~~~~~ Shillelagh uses a plugin registry similar to SQLAlchemy's. Adapters that are registered via entry points are registered automatically, but you can manually register adapter classes: .. code-block:: Python from shillelagh.adapters.base import Adapter from shillelagh.adapters.registry import registry class CustomAdapter(Adapter): ... # add an adapter class directly registry.add('customadapter', CustomAdapter) # add an adapter class by passing the module path and class name registry.register('someotheradapter', 'path.to.module', 'ClassName') SQLAlchemy ========== Shillelagh implements a SQLAlchemy dialect called ``shillelagh``: .. code-block:: python from sqlalchemy.engine import create_engine engine = create_engine("shillelagh://") connection = engine.connect() query = "SELECT * FROM a_table" for row in connection.execute(query): print(row) Configuration ~~~~~~~~~~~~~ The SQLAlchemy engine can be configured in the same way as the :ref:`dbapi2` ``connect`` function, defining the adapters to be loaded, passing custom keyword arguments to the adapters, or loading only safe adapters. For example, if you want to connect only to Google Spreadsheets, using credentials from a service account: .. code-block:: python from sqlalchemy.engine import create_engine engine = create_engine( "shillelagh://", adapters=["gsheetsapi"], adapter_kwargs={ "gsheetsapi": { "service_account_file": "/path/to/credentials.json", "subject": "user@example.com", }, }, ) Alternatively, Shillelagh also comes with a custom Google Sheets dialect for SQLAlchemy. See :ref:`gsheets` for more details. Command-line utility ==================== Shillelagh comes with a simple command-line utility aptly named ``shillelagh``: .. code-block:: bash $ shillelagh sql> SELECT * FROM "https://docs.google.com/spreadsheets/d/1_rN3lm0R_bU3NemO0s9pbFkY5LQPcuy1pscv8ZXPtg8/edit#gid=0"; country cnt --------- ----- BR 1 BR 3 IN 5 ZA 6 CR 10 sql> The ``shillelagh`` application has very simple autocomplete, and runs the query on :kbd:`return`. Configuration ~~~~~~~~~~~~~ The command-line utility can be configured through a YAML file stored in ``~/.config/shillelagh/shillelagh.yaml``. The contents of the file correspond to the ``adapter_kwargs`` argument, eg: .. code-block:: YAML gsheetsapi: service_account_file: /path/to/credentials.json subject: user@example.com weatherapi: api_key: XXX Custom functions ================ Shillelagh exposes a few custom functions that can be called via SQL. Sleep ~~~~~ The ``sleep`` function is useful to create long-running queries, in order to test time outs in your application. .. code-block:: sql sql> SELECT sleep(120); This will return ``None`` after 2 minutes. Retrieving metadata ~~~~~~~~~~~~~~~~~~~ The ``get_metadata`` function returns metadata about a special table as a JSON string, including which adapter handles it: .. code-block:: sql> SELECT GET_METADATA("https://docs.google.com/spreadsheets/d/1_rN3lm0R_bU3NemO0s9pbFkY5LQPcuy1pscv8ZXPtg8/edit#gid=0"); GET_METADATA("https://docs.google.com/spreadsheets/d/1_rN3lm0R_bU3NemO0s9pbFkY5LQPcuy1pscv8ZXPtg8/edit#gid=0") -------------------------------------------------------------------------------------------------------------- { "extra": { "Spreadsheet title": "Shillelagh GSheets", "Sheet title": "Simple sheet" }, "adapter": "GSheetsAPI" } Finding out the version ~~~~~~~~~~~~~~~~~~~~~~~ Sometimes it's useful to identify the version of Shillelagh that's running on a system, in order to troubleshoot it. You can do that with ``version()``: .. code-block:: sql sql> SELECT VERSION(); VERSION() ----------- 1.0.0