NLQueries reads two kinds of sources: databases (for structured SQL answers) and documents (for the document and hybrid agents).
| Connector | Install | Query history source |
|---|---|---|
| PostgreSQL | included | pg_stat_statements extension |
| MySQL / MariaDB | pip install "nlqueries-core[mysql]" |
None — served via the generic SQLAlchemy connector (see below) |
| Snowflake | pip install "nlqueries-core[snowflake]" |
QUERY_HISTORY view in INFORMATION_SCHEMA |
| BigQuery | pip install "nlqueries-core[bigquery]" |
INFORMATION_SCHEMA.JOBS |
| Amazon Redshift | pip install "nlqueries-core[redshift]" |
STL_QUERY (requires superuser or pg_read_all_stats) |
| SQL Server / Azure SQL | pip install "nlqueries-core[mssql]" |
sys.dm_exec_query_stats + sys.dm_exec_sql_text (requires VIEW SERVER STATE / VIEW DATABASE STATE) |
| DuckDB | pip install "nlqueries-core[duckdb]" |
None — file-based, no persisted history |
| Any other SQL database (generic SQLAlchemy) | included — plus the database's own driver | None — no portable history source |
The six dedicated connectors above are purpose-built for their databases (schema introspection, query-history mining, dialect quirks). The generic SQLAlchemy connector reaches any other database SQLAlchemy can talk to — MySQL/MariaDB, SQLite, Oracle, and more — from a connection URL. See cli-reference for connect examples per type.
process-history requires the pg_stat_statements extension. Check whether it's already enabled before changing anything:
SHOW shared_preload_libraries; -- library loaded at server level?
SELECT extname FROM pg_extension WHERE extname = 'pg_stat_statements'; -- extension created in this DB?
Managed databases (AWS RDS, Google Cloud SQL, Supabase, Neon, Azure Database for PostgreSQL) pre-load the library — just run:
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
Self-hosted PostgreSQL requires a restart, since shared_preload_libraries is a startup-only parameter:
shared_preload_libraries = 'pg_stat_statements' to postgresql.conf (append with a comma if other libraries are already listed)CREATE EXTENSION IF NOT EXISTS pg_stat_statements; once per databaseSELECT count(*) FROM pg_stat_statements;Note: --days has no effect on PostgreSQL — pg_stat_statements doesn't record per-query timestamps, so all history since the last pg_stat_statements_reset() is returned. --days is honoured on Snowflake and BigQuery, which do track execution time.
Schema descriptions are not available (no equivalent of PostgreSQL's pg_description). Row counts come from SVV_TABLE_INFO (requires table-owner or superuser; falls back to a permission-free list if inaccessible).
Use alice@my-server as --user for Azure SQL with SQL authentication — the same connector covers on-premises SQL Server and Azure SQL since the T-SQL dialect is identical. If the account lacks VIEW SERVER STATE/VIEW DATABASE STATE, process-history returns empty history and the KB is built from schema introspection only.
No query history across connections — process-history always returns an empty list; the KB comes from schema introspection only. Primary keys are detected via duckdb_constraints(); foreign keys are skipped (rarely declared in DuckDB analytics workloads).
For any database not covered by a dedicated connector — MySQL/MariaDB, SQLite, Oracle, and others — NLQueries ships a generic SQLAlchemy connector driven entirely by a connection URL. Schema is introspected dialect-agnostically through SQLAlchemy's inspector, so tables, columns, and relationships are discovered automatically. Install the database's own driver (e.g. pip install "nlqueries-core[mysql]" for pymysql) and register it in ~/.nlqueries/connectors.yaml with db_type: sqlalchemy and a url:
connectors:
analytics:
db_type: sqlalchemy
url: mysql+pymysql://user:password@localhost:3306/analytics
# other examples:
# url: sqlite:////data/warehouse.db
# url: oracle+oracledb://user:password@host:1521/?service_name=ORCLPDB1
Then query it like any other connector: nlqueries query analytics "how many orders shipped last month?". Two limits to know: query-history mining isn't available (there's no portable cross-dialect source), so the knowledge base is built from schema introspection only; and a per-statement timeout is enforced best-effort per dialect (see CONNECTOR_STATEMENT_TIMEOUT_SECONDS in configuration). The dedicated connect command doesn't register this connector type — add the entry to connectors.yaml directly as shown above.
| Connector | Format | Requires |
|---|---|---|
.pdf |
pip install "nlqueries-core[docs]" |
|
| Word | .docx |
pip install "nlqueries-core[docs]" |
| Excel | .xlsx |
pip install "nlqueries-core[docs]" |
| Notion | Notion pages | pip install "nlqueries-core[wiki]", NOTION_API_TOKEN |
| Confluence | Confluence spaces | pip install "nlqueries-core[wiki]", CONFLUENCE_URL, CONFLUENCE_USER, CONFLUENCE_API_TOKEN |
# SOURCE_ID is an opaque slug you choose (e.g. a UUID or short name)
nlq doc-ingest <source_id> <file_path>
# e.g.
nlq doc-ingest q1-report ./report.pdf
# Notion — requires NOTION_API_TOKEN env var; PAGE_ID is the Notion page or database ID
nlq doc-sync-notion <source_id> <page_id>
# e.g.
NOTION_API_TOKEN=secret_... nlq doc-sync-notion my-wiki-src abc123def456
# Confluence — requires CONFLUENCE_API_TOKEN env var
nlq doc-sync-confluence <source_id> <space_key> --base-url <url> --username <user>
# e.g.
CONFLUENCE_API_TOKEN=... nlq doc-sync-confluence my-src ENG \
--base-url https://acme.atlassian.net --username alice@acme.com
After ingestion, documents are chunked and embedded into Qdrant (required — see qdrant-setup). The document agent retrieves relevant chunks automatically when answering; citations (source document, page/section) are included in the answer.
Query with nlq doc-ask doc_{source_id}_chunks "..." for a document-only answer (the collection name follows the pattern doc_{source_id}_chunks), or use nlqueries query for the orchestrator to route automatically (including hybrid SQL + document answers).
Text splitting: document ingestion uses a small built-in text splitter — there's no langchain dependency, so document connectors work on every supported Python version. See troubleshooting if ingestion fails to import a format library (install the [docs] or [wiki] extra).