{"id":27059943,"url":"https://github.com/tddschn/questdb-api","last_synced_at":"2025-04-05T13:17:08.824Z","repository":{"id":285475465,"uuid":"958268220","full_name":"tddschn/questdb-api","owner":"tddschn","description":"QuestDB REST API Python Client, CLI and REPL Shell (alias of https://github.com/tddschn/questdb-rest)","archived":false,"fork":false,"pushed_at":"2025-03-31T23:37:36.000Z","size":66,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-01T00:26:52.679Z","etag":null,"topics":["python-sdk","questdb"],"latest_commit_sha":null,"homepage":"https://teddysc.me/blog/questdb-rest","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tddschn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-31T23:23:34.000Z","updated_at":"2025-03-31T23:57:09.000Z","dependencies_parsed_at":"2025-04-01T00:36:54.421Z","dependency_job_id":null,"html_url":"https://github.com/tddschn/questdb-api","commit_stats":null,"previous_names":["tddschn/questdb-api"],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tddschn%2Fquestdb-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tddschn%2Fquestdb-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tddschn%2Fquestdb-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tddschn%2Fquestdb-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tddschn","download_url":"https://codeload.github.com/tddschn/questdb-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247339155,"owners_count":20923014,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["python-sdk","questdb"],"created_at":"2025-04-05T13:17:08.280Z","updated_at":"2025-04-05T13:17:08.807Z","avatar_url":"https://github.com/tddschn.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# QuestDB REST API Python Client, CLI and REPL Shell\n\n\u003e QuestDB comes with a very nice web console, but there's no CLI, so I wrote one (can't live without the terminal!).\n\nThe REST API is very well defined: https://questdb.com/docs/reference/api/rest/, only 3 documented endpoints. One undocumented endpoints I also implemented are `/chk` to check for if a table exists, I found the route when trying to ingest CSV via the web console.\n\n- [QuestDB REST API Python Client, CLI and REPL Shell](#questdb-rest-api-python-client-cli-and-repl-shell)\n  - [How's this different from the official `py-questdb-client` and `py-questdb-query` packages?](#hows-this-different-from-the-official-py-questdb-client-and-py-questdb-query-packages)\n  - [Features beyond what the vanilla REST API provides](#features-beyond-what-the-vanilla-rest-api-provides)\n    - [Docs, screenshots and video demos](#docs-screenshots-and-video-demos)\n    - [`imp` programmatically derives table name from filename when uploading CSVs](#imp-programmatically-derives-table-name-from-filename-when-uploading-csvs)\n    - [`exec` supports multiple queries in one go](#exec-supports-multiple-queries-in-one-go)\n    - [Query output parsing and formatting](#query-output-parsing-and-formatting)\n    - [`schema`](#schema)\n    - [`chk`](#chk)\n  - [Usage](#usage)\n    - [Global options to fine tune log levels](#global-options-to-fine-tune-log-levels)\n    - [Configuring CLI - DB connection options](#configuring-cli---db-connection-options)\n  - [PyPI packages and installation](#pypi-packages-and-installation)\n  - [The Python API](#the-python-api)\n  - [Screenshots](#screenshots)\n\n## How's this different from the official `py-questdb-client` and `py-questdb-query` packages?\n\n- `py-questdb-client`: Focuses on ingestion from Python data structures and / or DataFrames, I don't think it does anything else\n- `py-questdb-query`: Cython based library to get numpy arrays or dataframes from the REST API\n- This python client: Gets raw JSON from REST API, doesn't depend on numpy or pandas, making the CLI lightweight and fast to start\n\n## Features beyond what the vanilla REST API provides\n\n\n### Docs, screenshots and video demos\n\nOriginally I just wrote the CLI (`cli.py`), then it becomes really complicated that I had to split the code and put the REST API interfacing part into a module (`__init__.py`).\n\n- Write up and demo: https://teddysc.me/blog/questdb-rest\n- 6 min demo: https://www.youtube.com/watch?v=l_1HBbAHeBM\n- https://teddysc.me/blog/rlwrap-questdb-shell\n- GitHub: https://github.com/tddschn/questdb-rest\n- PyPI: https://pypi.org/project/questdb-rest/\n- QuestDB-Shell: https://github.com/tddschn/questdb-shell\n\n### `imp` programmatically derives table name from filename when uploading CSVs\n\n`questdb-cli imp` options that are not part of the REST API spec:\n```\n  --name-func {stem,add_prefix}\n                        Function to generate table name from filename (ignored if --name set). Available: stem, add_prefix (default: None)\n  --name-func-prefix NAME_FUNC_PREFIX\n                        Prefix string for 'add_prefix' name function. (default: )\n  -D, --dash-to-underscore\n                        If table name is derived from filename (i.e., --name not set), convert dashes (-) to underscores (_). Compatible with --name-func. (default: False)\n```\n\nGlobal flag `--stop-on-error` controls if it should stop talking to the API on first CSV import error or not.\n\n### `exec` supports multiple queries in one go\n\nThe API and web console will only take your last query if you attempt to give it more than 1, while this project uses `sqlparser` to split the queries and send them one by one for you for convenience. Global flag `--stop-on-error` controls if it should stop talking to the API on first error or not. Since the API doesn't always return a status code other than 200 on error, I dived in to the Dev Tools to see what exactly tells me if a request is successful or not.\n\nThe queries can be piped in from stdin, or read from a file, or you can supply it from the command line.\n\n\n\n### Query output parsing and formatting\n\nThe `/exec` endpoints only speaks JSON, this tool gives you options to format the output table to as markdown with `--markdown` or a psql-style ASCII table with `--psql` (default is JSON).\n\nFor CSV output, use `questdb-cli exp` instead.\n\n### `schema`\n\nConvenience command to fetch schema for 1 or more tables. Hard to do without reading good chunk of the QuestDB doc. The web console supports copying schemas from the tables list.\n\n```\nqdb-cli schema equities_1d\n\nCREATE TABLE 'equities_1d' ( \n\ttimestamp TIMESTAMP,\n\topen DOUBLE,\n\thigh DOUBLE,\n\tlow DOUBLE,\n\tclose DOUBLE,\n\tvolume LONG,\n\tticker SYMBOL CAPACITY 1024 CACHE\n) timestamp(timestamp) PARTITION BY YEAR WAL\nWITH maxUncommittedRows=500000, o3MaxLag=600000000us\nDEDUP UPSERT KEYS(timestamp,ticker);\n```\n### `chk`\n\nThe `chk` command to talk to `/chk` endpoint, which is used by the web console's CSV upload UI.\n\n## Usage\n\n### Global options to fine tune log levels\n\n```\nqdb-cli -h\n\nusage: questdb-cli [-h] [-H HOST] [--port PORT] [-u USER] [-p PASSWORD]\n                   [--timeout TIMEOUT] [--scheme {http,https}] [-i | -D] [-R]\n                   [--config CONFIG] [--stop-on-error | --no-stop-on-error]\n                   {imp,exec,exp,chk,schema,gen-config} ...\nQuestDB REST API Command Line Interface.\nLogs to stderr, outputs data to stdout.\nUses QuestDB REST API via questdb_rest library.\npositional arguments:\n  {imp,exec,exp,chk,schema,gen-config}\n                        Available sub-commands\n    imp                 Import data from file(s) using /imp.\n    exec                Execute SQL statement(s) using /exec (returns JSON).\n                        Reads SQL from --query, --file, --get-query-from-python-module, or stdin.\n    exp                 Export data using /exp (returns CSV to stdout or file).\n    chk                 Check if a table exists using /chk (returns JSON). Exit code 0 if exists, 3 if not.\n    schema              Fetch CREATE TABLE statement(s) for one or more tables.\n    gen-config          Generate a default config file at ~/.questdb-rest/config.json\noptions:\n  -h, --help            Show this help message and exit.\n  -H HOST, --host HOST  QuestDB server host.\n  --port PORT           QuestDB REST API port.\n  -u USER, --user USER  Username for basic authentication.\n  -p PASSWORD, --password PASSWORD\n                        Password for basic authentication. If -u is given but -p is not, will prompt securely unless password is in config.\n  --timeout TIMEOUT     Request timeout in seconds.\n  --scheme {http,https}\n                        Connection scheme (http or https).\n  -i, --info            Use info level logging (default is WARNING).\n  -D, --debug           Enable debug level logging to stderr.\n  -R, --dry-run         Simulate API calls without sending them. Logs intended actions.\n  --config CONFIG       Path to a specific config JSON file (overrides default ~/.questdb-rest/config.json).\n  --stop-on-error, --no-stop-on-error\n                        Stop execution immediately if any item (file/statement/table) fails.\n```\n\n### Configuring CLI - DB connection options\n\nRun `qdb-cli gen-config` and edit the generated config file to specify your DB's port, host, and auth info.\n\nAll options are optional and will use the default `localhost:9000` if not specified.\n\n## PyPI packages and installation\n\n`questdb-cli`, `questdb-rest` and `questdb-api` are the same package (just aliases), with `questdb-rest` guaranteed to be the most updated.\n\nInstalling any of them will give you the `questdb-cli` and `qdb-cli` commands (same thing).\n\nInstall (Python \u003e=3.11 required):\n\n```bash\nuv tool install questdb-rest\n```\n\n```bash\npipx install questdb-rest\n```\n\n```bash\n# not recommended, but if you really want to:\npip install questdb-rest\n```\n\n\n## The Python API\n\nThese classes are provided with extensive methods to interact with the REST API (it's all in `__init__.py`).\n\n```plain\nQuestDBError\nQuestDBConnectionError\nQuestDBAPIError\nQuestDBClient\n```\n\n## Screenshots\n\n![CleanShot-2025-03-30-16.25.07](https://g.teddysc.me/tddschn/16651cccc351b1d2742a4bddaee1c62d/CleanShot-2025-03-30-16.25.07@2x_base64.txt?b)\n![CleanShot-2025-03-30-16.32.44](https://g.teddysc.me/tddschn/16651cccc351b1d2742a4bddaee1c62d/CleanShot-2025-03-30-16.32.44_base64.txt?b)\n![CleanShot-2025-03-30-16.33.18](https://g.teddysc.me/tddschn/16651cccc351b1d2742a4bddaee1c62d/CleanShot-2025-03-30-16.33.18_base64.txt?b)\n![CleanShot-2025-03-30-16.33.36](https://g.teddysc.me/tddschn/16651cccc351b1d2742a4bddaee1c62d/CleanShot-2025-03-30-16.33.36_base64.txt?b)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftddschn%2Fquestdb-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftddschn%2Fquestdb-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftddschn%2Fquestdb-api/lists"}