### Install Harlequin and Database Adapters Source: https://context7.com/tconbeer/harlequin/llms.txt This section provides instructions for installing Harlequin and its database adapter plugins using package managers like uv, pip, and Homebrew. It shows how to install the base Harlequin package, install with specific adapter extras, install multiple adapters simultaneously, and install adapters as separate packages. Dependencies include uv, pip, or Homebrew depending on the installation method. ```bash # Install base Harlequin with uv (recommended) uv tool install harlequin # Install with PostgreSQL adapter as extra uv tool install 'harlequin[postgres]' # Install multiple adapters at once uv tool install 'harlequin[postgres,mysql,bigquery]' # Install with pip pip install harlequin # Install adapter plugins separately pip install harlequin-postgres harlequin-mysql # Install from Homebrew (includes postgres, mysql, odbc adapters) brew install harlequin ``` -------------------------------- ### Install Harlequin with Database Adapters using uv Source: https://github.com/tconbeer/harlequin/blob/main/README.md Installs Harlequin along with specified database adapter extras using `uv`. Multiple adapters can be installed by listing them within the brackets. ```bash uv tool install 'harlequin[postgres]' ``` ```bash uv tool install 'harlequin[postgres,mysql,s3]' ``` -------------------------------- ### Install uv Standalone Installer Source: https://github.com/tconbeer/harlequin/blob/main/README.md Installs the `uv` package manager using a curl script for POSIX shells or a PowerShell script for Windows. This is the recommended method for installing Harlequin. ```bash curl -LsSf https://astral.sh/uv/install.sh | sh ``` ```powershell powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" ``` -------------------------------- ### Install Harlequin using uv Source: https://github.com/tconbeer/harlequin/blob/main/README.md Installs Harlequin as a tool using `uv`, which places it in an isolated environment and adds it to the system's PATH for easy execution. ```bash uv tool install harlequin ``` -------------------------------- ### Launch Harlequin IDE from Command Line Source: https://context7.com/tconbeer/harlequin/llms.txt This section demonstrates how to launch the Harlequin SQL IDE using various command-line arguments. It covers connecting to different database types (DuckDB, SQLite, PostgreSQL), setting options like result limits and themes, and displaying version information. No specific dependencies are mentioned beyond the Harlequin installation itself. ```bash # Start with in-memory DuckDB database harlequin # Connect to local DuckDB database files harlequin path/to/database.db another.db # Use SQLite adapter with database file harlequin -a sqlite path/to/database.sqlite # Connect to PostgreSQL with installed adapter harlequin -a postgres "postgresql://user:pass@localhost:5432/mydb" # Set result limit and theme harlequin --limit 50000 --theme monokai path/to/data.db # Show local files in data catalog harlequin --show-files /path/to/data/directory # Use configuration profile from .harlequin.toml harlequin --profile production # Display version and installed adapters harlequin --version ``` -------------------------------- ### Install Harlequin using pip Source: https://github.com/tconbeer/harlequin/blob/main/README.md Installs Harlequin using the Python package installer `pip`. This method requires Python 3.9 or above and assumes you have `pip` available. ```bash pip install harlequin ``` -------------------------------- ### Install Harlequin using Homebrew Source: https://github.com/tconbeer/harlequin/blob/main/README.md Installs Harlequin using the Homebrew package manager. This formula includes several database adapters and their dependencies, which may increase the application size. ```bash brew install harlequin ``` -------------------------------- ### Define Harlequin Adapter Configuration Options (Python) Source: https://context7.com/tconbeer/harlequin/llms.txt Defines typed configuration options for adapter-specific settings in Harlequin. This includes text, path, select, flag, and list options, with examples of validation and usage within an adapter class. Dependencies include harlequin.options. ```python from harlequin.options import ( TextOption, PathOption, SelectOption, FlagOption, ListOption, ) # Text input with validation def validate_port(raw: str) -> tuple[bool, str | None]: """Validate port is numeric and in valid range.""" try: port = int(raw) if 1 <= port <= 65535: return True, None return False, "Port must be between 1 and 65535" except ValueError: return False, "Port must be a number" PORT_OPTION = TextOption( name="port", description="Database server port number", short_decls=["-p"], default="5432", placeholder="5432", validator=validate_port, ) # Path input for files/directories INIT_SCRIPT_OPTION = PathOption( name="init-script", description="SQL initialization script to run on connect", exists=True, file_okay=True, dir_okay=False, default="~/.mydbinitrc", ) # Select from predefined choices SSL_MODE_OPTION = SelectOption( name="ssl-mode", description="SSL connection mode", choices=[ ("disable", "disable"), ("require", "require"), ("verify-ca", "verify-ca"), ("verify-full", "verify-full"), ], default="prefer", ) # Boolean flag READ_ONLY_OPTION = FlagOption( name="read-only", description="Open connection in read-only mode", short_decls=["-r"], default=False, ) # Multiple values EXTENSIONS_OPTION = ListOption( name="extension", description="Load database extension (can be repeated)", short_decls=["-e"], ) # Usage in adapter class MyAdapter(HarlequinAdapter): ADAPTER_OPTIONS = [ PORT_OPTION, INIT_SCRIPT_OPTION, SSL_MODE_OPTION, READ_ONLY_OPTION, EXTENSIONS_OPTION, ] ``` -------------------------------- ### View Harlequin Help Source: https://github.com/tconbeer/harlequin/blob/main/README.md Displays all available options and arguments for the Harlequin command-line interface, useful for understanding its full capabilities. ```bash harlequin --help ``` -------------------------------- ### Test Database Adapters in Python using Pytest Source: https://context7.com/tconbeer/harlequin/llms.txt This Python code provides a comprehensive test suite for database adapter implementations using the pytest framework. It covers adapter initialization, connection establishment, query execution, error handling, catalog retrieval, and result limiting. Dependencies include 'pytest' and 'harlequin'. ```python import pytest from harlequin.exception import HarlequinConnectionError, HarlequinQueryError from my_adapter import MyDatabaseAdapter, MyDatabaseConnection def test_adapter_initialization(): """Test adapter accepts valid configuration.""" adapter = MyDatabaseAdapter( conn_str=["testdb"], host="localhost", port="5432", read_only=True, ) assert adapter.host == "localhost" assert adapter.port == "5432" assert adapter.read_only is True def test_adapter_connection(test_database): """Test adapter establishes connection.""" adapter = MyDatabaseAdapter(conn_str=[test_database]) conn = adapter.connect() assert isinstance(conn, MyDatabaseConnection) conn.close() def test_query_execution(test_connection): """Test query execution returns results.""" cursor = test_connection.execute("SELECT 1 as num, 'test' as str") assert cursor is not None columns = cursor.columns() assert columns == [("num", "#"), ("str", "s")]) data = cursor.fetchall() assert len(data) == 1 assert data[0] == (1, "test") def test_query_error_handling(test_connection): """Test invalid queries raise HarlequinQueryError.""" with pytest.raises(HarlequinQueryError): test_connection.execute("INVALID SQL SYNTAX") def test_catalog_retrieval(test_connection): """Test catalog introspection.""" catalog = test_connection.get_catalog() assert len(catalog.items) > 0 assert all(hasattr(item, "label") for item in catalog.items) def test_result_limiting(test_connection): """Test cursor respects row limit.""" cursor = test_connection.execute("SELECT * FROM large_table") cursor.set_limit(100) data = cursor.fetchall() assert len(data) <= 100 @pytest.fixture def test_database(tmp_path): """Provide temporary test database.""" db_path = tmp_path / "test.db" # Create and populate test database yield str(db_path) @pytest.fixture def test_connection(test_database): """Provide test database connection.""" adapter = MyDatabaseAdapter(conn_str=[test_database]) conn = adapter.connect() yield conn conn.close() ``` -------------------------------- ### Run Harlequin Command Source: https://github.com/tconbeer/harlequin/blob/main/README.md Basic command structure for running Harlequin from the terminal. It accepts options and connection strings to specify database adapters and connection details. ```bash harlequin [OPTIONS] [CONN_STR] ``` -------------------------------- ### Run Harlequin with DuckDB (Database Files) Source: https://github.com/tconbeer/harlequin/blob/main/README.md Opens one or more DuckDB database files using Harlequin. The paths provided are used as connection strings, and Harlequin will create the database files if they do not exist. ```bash harlequin "path/to/duck.db" "another_duck.db" ``` -------------------------------- ### Create Harlequin Interactive Catalog Items (Python) Source: https://context7.com/tconbeer/harlequin/llms.txt Builds catalog items with lazy-loading children and context menu interactions using Python. It defines a `TableCatalogItem` that can fetch its columns dynamically and provides interactions like copying the name, showing row count, and describing the table. Dependencies include harlequin.catalog and harlequin.driver. ```python from dataclasses import dataclass from typing import ClassVar, Sequence from harlequin.catalog import CatalogItem, InteractiveCatalogItem, Interaction from harlequin.driver import HarlequinDriver @dataclass class TableCatalogItem(InteractiveCatalogItem): """Table item with lazy-loaded columns and interactions.""" INTERACTIONS: ClassVar[list[tuple[str, Interaction]]] = [ ("Copy Name", lambda item, driver: driver.copy_to_clipboard(item.query_name)), ("View Row Count", show_row_count), ("Describe Table", describe_table), ] database: str = "" schema: str = "" table: str = "" def fetch_children(self) -> Sequence[CatalogItem]: """Lazy-load column definitions for this table.""" if not self.connection: return [] columns = self.connection._get_columns( self.database, self.schema, self.table ) return [ CatalogItem( qualified_identifier=f'\"{self.database}\". \"{self.schema}\" . \"{self.table}\" . \"{col_name}\" ', query_name=f'\"{col_name}\" ', label=col_name, type_label=self._short_type(col_type), children=[], ) for col_name, col_type in columns ] @staticmethod def _short_type(native_type: str) -> str: """Convert type to short label.""" return {"VARCHAR": "s", "INTEGER": "#", "TIMESTAMP": "ts"}.get( native_type.upper(), "?" ) def show_row_count(item: TableCatalogItem, driver: HarlequinDriver) -> None: """Count rows and display notification.""" query = f"SELECT COUNT(*) FROM {item.qualified_identifier}" try: cursor = item.connection.execute(query) if cursor: result = cursor.fetchall() count = result[0][0] if result else 0 driver.show_notification(f"{item.label}: {count:,} rows") except Exception as e: driver.show_error("Row Count Failed", str(e)) def describe_table(item: TableCatalogItem, driver: HarlequinDriver) -> None: """Insert DESCRIBE statement into query editor.""" query = f"DESCRIBE {item.qualified_identifier};" driver.insert_text_at_selection(query) ``` -------------------------------- ### Run Harlequin with DuckDB (In-Memory) Source: https://github.com/tconbeer/harlequin/blob/main/README.md Launches Harlequin using its default DuckDB adapter, opening an in-memory DuckDB database session. No arguments are needed for this default behavior. ```bash harlequin ``` -------------------------------- ### Implement Custom Database Adapter in Python Source: https://context7.com/tconbeer/harlequin/llms.txt This Python code demonstrates how to implement a custom database adapter for Harlequin. It defines `MyDatabaseCursor` for fetching and formatting query results, `MyDatabaseConnection` for executing queries and introspecting the database schema, and `MyDatabaseAdapter` for establishing connections. It requires a database library (aliased as `db`) and assumes a specific schema introspection query. The adapter options, like host, port, and read-only mode, are configurable. ```python from pathlib import Path from typing import Any, Sequence from harlequin import ( HarlequinAdapter, HarlequinConnection, HarlequinCursor, HarlequinAdapterOption, ) from harlequin.catalog import Catalog, CatalogItem from harlequin.exception import HarlequinConnectionError, HarlequinQueryError from harlequin.options import TextOption, FlagOption import your_database_library as db class MyDatabaseCursor(HarlequinCursor): def __init__(self, cursor: Any) -> None: self.cursor = cursor self._limit: int | None = None def columns(self) -> list[tuple[str, str]]: """Return list of (column_name, type_label) tuples.""" return [ (col.name, self._short_type(col.type)) for col in self.cursor.description ] def set_limit(self, limit: int) -> "MyDatabaseCursor": """Set maximum rows to fetch.""" self._limit = limit return self def fetchall(self) -> list[tuple] | None: """Fetch result data, respecting limit if set.""" try: if self._limit: return self.cursor.fetchmany(self._limit) return self.cursor.fetchall() except db.Error as e: raise HarlequinQueryError( msg=str(e), title="Database error fetching results" ) from e @staticmethod def _short_type(native_type: str) -> str: """Convert native type to short display label.""" type_map = { "INTEGER": "#", "VARCHAR": "s", "TIMESTAMP": "ts", "BOOLEAN": "t/f", } return type_map.get(native_type.upper(), "?") class MyDatabaseConnection(HarlequinConnection): def __init__(self, conn: Any, init_message: str = "") -> None: self.conn = conn self.init_message = init_message def execute(self, query: str) -> MyDatabaseCursor | None: """Execute query and return cursor or None for DDL.""" try: cursor = self.conn.execute(query) if cursor.description: return MyDatabaseCursor(cursor) return None except db.Error as e: raise HarlequinQueryError( msg=str(e), title="Query execution failed" ) from e def get_catalog(self) -> Catalog: """Introspect database and return catalog structure.""" items = [] cursor = self.conn.execute( "SELECT table_schema, table_name FROM information_schema.tables" ) for schema, table in cursor.fetchall(): items.append( CatalogItem( qualified_identifier=f'\"{schema}\".\"{table}\"", query_name=f'\"{schema}\".\"{table}\"", label=table, type_label="t", children=[] ) ) return Catalog(items=items) def close(self) -> None: """Close database connection.""" self.conn.close() class MyDatabaseAdapter(HarlequinAdapter): ADAPTER_OPTIONS = [ TextOption( name="host", description="Database server hostname", default="localhost", ), TextOption( name="port", description="Database server port", default="5432", ), FlagOption( name="read-only", description="Open connection in read-only mode", ), ] def __init__( self, conn_str: Sequence[str], host: str = "localhost", port: str = "5432", read_only: bool = False, **kwargs: Any, ) -> None: self.conn_str = conn_str self.host = host self.port = port self.read_only = read_only def connect(self) -> MyDatabaseConnection: """Establish database connection.""" try: connection = db.connect( database=self.conn_str[0] if self.conn_str else "default", host=self.host, port=int(self.port), read_only=self.read_only, ) return MyDatabaseConnection( conn=connection, init_message=f"Connected to {self.host}:{self.port}" ) except db.ConnectionError as e: raise HarlequinConnectionError( msg=str(e), title="Failed to connect to database" ) from e # Register adapter as entry point in pyproject.toml: # [project.entry-points."harlequin.adapter"] # mydatabase = "mypackage:MyDatabaseAdapter" ``` -------------------------------- ### Run Harlequin with SQLite (Database Files) Source: https://github.com/tconbeer/harlequin/blob/main/README.md Opens one or more SQLite database files using Harlequin with the `-a` alias for the `--adapter` option. Paths are provided as connection strings. ```bash harlequin -a sqlite "path/to/sqlite.db" "another_sqlite.db" ``` -------------------------------- ### Run Harlequin with SQLite (In-Memory) Source: https://github.com/tconbeer/harlequin/blob/main/README.md Launches Harlequin and explicitly uses the SQLite adapter to open an in-memory SQLite database session. The `--adapter` or `-a` option specifies the adapter. ```bash harlequin --adapter sqlite ``` -------------------------------- ### Configure Harlequin with TOML Files Source: https://context7.com/tconbeer/harlequin/llms.txt Defines Harlequin profiles and keymaps in `.harlequin.toml` configuration files. This TOML snippet shows how to set a default profile, define connection profiles for different databases (duckdb, postgres, sqlite) with various settings like connection strings, themes, limits, and read-only modes. ```toml # .harlequin.toml - place in home directory or project root # Default profile loaded automatically default_profile = "dev" # Define connection profiles [profiles.dev] adapter = "duckdb" conn_str = ["./dev.db"] theme = "harlequin" limit = 100000 show_files = "./data" [profiles.prod] adapter = "postgres" conn_str = ["postgresql://user:pass@prod-db.example.com:5432/analytics"] theme = "monokai" limit = 500000 read_only = true [profiles.local-sqlite] adapter = "sqlite" conn_str = ["./local.sqlite"] theme = "github-dark" ``` -------------------------------- ### Provide Custom Autocomplete Completions in Python Source: https://context7.com/tconbeer/harlequin/llms.txt Extend Harlequin's autocomplete functionality by providing custom SQL keywords and functions. This Python code defines a custom connection class that overrides the `get_completions` method to return a list of `HarlequinCompletion` objects. ```python from harlequin import HarlequinConnection, HarlequinCompletion class MyConnection(HarlequinConnection): def get_completions(self) -> list[HarlequinCompletion]: """Provide custom SQL completions for autocomplete.""" return [ HarlequinCompletion( label="EXPLAIN ANALYZE", type_label="kw", value="EXPLAIN ANALYZE ", priority=1000, context=None, ), HarlequinCompletion( label="current_timestamp", type_label="fn", value="current_timestamp()", priority=900, context=None, ), HarlequinCompletion( label="date_trunc", type_label="fn", value="date_trunc('day', $1)", priority=900, context=None, ), HarlequinCompletion( label="RETURNING", type_label="kw", value="RETURNING ", priority=800, context=None, ), ] # Completions supplement catalog-based completions # Harlequin automatically creates completions for: # - Database names # - Schema names # - Table names # - Column names # - View names ``` -------------------------------- ### Load Iris Dataset and Insert into DuckDB (Python) Source: https://github.com/tconbeer/harlequin/blob/main/tests/data/unit_tests/completions/README.md This Python script loads the Iris dataset using scikit-learn, converts it to a Pandas DataFrame, connects to a DuckDB database, creates an 'iris' table, inserts the data, and optionally prints the first 5 rows to verify. Dependencies include scikit-learn, pandas, and duckdb. ```python from sklearn.datasets import load_iris import pandas as pd import duckdb # Load the iris dataset iris = load_iris() iris_df = pd.DataFrame(data=iris.data, columns=iris.feature_names) iris_df["target"] = iris.target iris_df["species"] = pd.Categorical.from_codes(iris.target, iris.target_names) # Connect to DuckDB (this will create a new database if it doesn't exist) con = duckdb.connect("iris.db") # Create and insert data into the table con.execute(r''' CREATE TABLE IF NOT EXISTS iris ( sepal_length FLOAT, sepal_width FLOAT, petal_length FLOAT, petal_width FLOAT, target INTEGER, species VARCHAR ) ''') # Insert the data con.execute("INSERT INTO iris SELECT * FROM iris_df") # Verify the data (optional) result = con.execute("SELECT * FROM iris LIMIT 5").fetchall() print("First 5 rows:", result) # Close the connection con.close() ``` -------------------------------- ### Define Custom Keymaps for Harlequin Source: https://context7.com/tconbeer/harlequin/llms.txt Customize key bindings for specific actions within Harlequin. This configuration allows users to map keyboard shortcuts to predefined actions like running queries, exporting data, or formatting SQL. ```toml # Use profile from CLI: # harlequin --profile prod # harlequin --profile dev --keymap-name vscode --keymap-name my_keys ``` -------------------------------- ### Implement Query Cancellation in Python Source: https://context7.com/tconbeer/harlequin/llms.txt Enable query interruption for long-running operations by implementing a custom connection and adapter. The `CancellableConnection` class allows for query cancellation via a `cancel` method, and `CancellableAdapter` enables the cancel button in the UI. ```python import threading from harlequin import HarlequinAdapter, HarlequinConnection class CancellableConnection(HarlequinConnection): def __init__(self, conn: Any) -> None: self.conn = conn self._query_thread: threading.Thread | None = None self._should_cancel = False def execute(self, query: str) -> HarlequinCursor | None: """Execute query in thread-safe manner.""" self._should_cancel = False try: # Some databases support native interrupt return self.conn.execute(query) except InterruptedError: return None def cancel(self) -> None: """Cancel in-flight queries.""" self._should_cancel = True # Call database-specific cancellation try: self.conn.cancel() except Exception: pass class CancellableAdapter(HarlequinAdapter): # Enable cancel button in UI IMPLEMENTS_CANCEL = True def connect(self) -> CancellableConnection: conn = create_connection() return CancellableConnection(conn) ``` -------------------------------- ### Implement Export Functionality in Python Source: https://context7.com/tconbeer/harlequin/llms.txt This Python code implements data export functionality for Harlequin, allowing queries to be saved to files in CSV, JSON, or Parquet formats. It extends the HarlequinConnection class and handles different export options like headers and delimiters for CSV. Dependencies include 'pathlib', 'typing', and 'harlequin'. ```python from pathlib import Path from typing import Any from harlequin import HarlequinConnection, HarlequinCopyFormat from harlequin.options import FlagOption, TextOption from harlequin.exception import HarlequinCopyError class ExportableConnection(HarlequinConnection): def copy( self, query: str, path: Path, format_name: str, options: dict[str, Any], ) -> None: """Export query results to file.""" try: cursor = self.execute(query) if not cursor: raise HarlequinCopyError( "Query returned no results to export", title="Export Failed" ) data = cursor.fetchall() if format_name == "csv": self._export_csv(data, path, options) elif format_name == "json": self._export_json(data, path, options) elif format_name == "parquet": self._export_parquet(data, path, options) else: raise HarlequinCopyError( f"Unknown format: {format_name}", title="Export Failed" ) except Exception as e: raise HarlequinCopyError( str(e), title="Export operation failed" ) from e def _export_csv( self, data: list, path: Path, options: dict[str, Any] ) -> None: """Export to CSV format.""" import csv with open(path, "w", newline="") as f: writer = csv.writer( f, delimiter=options.get("delimiter", ","), quotechar=options.get("quote_char", '"'), ) if options.get("header", True): writer.writerow([col[0] for col in self.cursor.columns()]) writer.writerows(data) # Define export formats CSV_FORMAT = HarlequinCopyFormat( name="csv", label="CSV", extensions=[".csv", ".tsv"], options=[ FlagOption( name="header", description="Include header row", default=True, ), TextOption( name="delimiter", description="Field delimiter character", default=",", ), ], ) class ExportAdapter(HarlequinAdapter): COPY_FORMATS = [CSV_FORMAT] ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.