{"id":25569698,"url":"https://github.com/jdbcx/jdbcx","last_synced_at":"2026-01-14T02:24:25.053Z","repository":{"id":177956336,"uuid":"659958479","full_name":"jdbcx/jdbcx","owner":"jdbcx","description":"JDBCX: Extended JDBC driver for dynamic multi-language queries with optional bridge server for federated datasource connectivity.","archived":false,"fork":false,"pushed_at":"2025-10-06T23:29:32.000Z","size":1389,"stargazers_count":26,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-07T01:11:44.282Z","etag":null,"topics":["dynamic-query","jdbc-driver","prql","scripting","sql"],"latest_commit_sha":null,"homepage":"https://jdbcx.github.io/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jdbcx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-06-29T00:08:43.000Z","updated_at":"2025-10-06T23:29:34.000Z","dependencies_parsed_at":"2024-03-17T10:27:32.601Z","dependency_job_id":"a8b3d107-ece9-4440-9e08-209eafcb94bc","html_url":"https://github.com/jdbcx/jdbcx","commit_stats":null,"previous_names":["jdbcx/jdbcx"],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/jdbcx/jdbcx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdbcx%2Fjdbcx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdbcx%2Fjdbcx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdbcx%2Fjdbcx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdbcx%2Fjdbcx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jdbcx","download_url":"https://codeload.github.com/jdbcx/jdbcx/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdbcx%2Fjdbcx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408711,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["dynamic-query","jdbc-driver","prql","scripting","sql"],"created_at":"2025-02-21T00:02:34.588Z","updated_at":"2026-01-14T02:24:25.048Z","avatar_url":"https://github.com/jdbcx.png","language":"Java","funding_links":[],"categories":["数据库开发"],"sub_categories":[],"readme":"# JDBCX\n\n[![GitHub release (latest SemVer including pre-releases)](https://img.shields.io/github/v/release/jdbcx/jdbcx?style=plastic\u0026include_prereleases\u0026label=Latest%20Release)](https://github.com/jdbcx/jdbcx/releases/) [![GitHub release (by tag)](https://img.shields.io/github/downloads/jdbcx/jdbcx/latest/total?style=plastic)](https://github.com/jdbcx/jdbcx/releases/) [![Docker Pulls](https://img.shields.io/docker/pulls/jdbcx/jdbcx?style=plastic)](https://hub.docker.com/r/jdbcx/jdbcx) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=jdbcx_jdbcx\u0026metric=coverage)](https://sonarcloud.io/summary/new_code?id=jdbcx_jdbcx) [![Sonatype Nexus (Snapshots)](https://img.shields.io/badge/Nightly%20Build-v0.8.0--SNAPSHOT-blue?link=https%3A%2F%2Fcentral.sonatype.com%2Fservice%2Frest%2Frepository%2Fbrowse%2Fmaven-snapshots%2Fio%2Fgithub%2Fjdbcx%2F)](https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/io/github/jdbcx/) [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/jdbcx/jdbcx)\n\n\u003cimg align=\"right\" width=\"96\" height=\"96\" src=\"https://avatars.githubusercontent.com/u/137983508\"\u003e\n\nJDBCX extends JDBC with enhanced data format and compression support, object mapping, advanced type conversion, and multi-language query capabilities. It simplifies federated queries through dynamic embedding and offers a remote bridge for seamless multi-source connectivity.\n\n![image](https://github.com/user-attachments/assets/db3d3e7a-1fa3-4f71-adc6-0af9f0df2b6c)\n\n## Quick Start\n\nGetting started with JDBCX is easy. Use it as a standard [JDBC driver](/driver), a standalone [bridge server](/server), or combine both functionalities.\n\n```bash\n# Using the standard JDBC driver\n$ docker run --rm -it jdbcx/jdbcx 'jdbc:duckdb:' 'select 2 as num'\nnum\n2\n\n# Using JDBCX as a drop-in replacement (with extensions)\n$ docker run --rm -it jdbcx/jdbcx 'jdbcx:duckdb:' 'select {{script:1+1}} as num'\nnum\n2\n$ docker run --rm -it jdbcx/jdbcx 'jdbcx:' \"{{ db.ch-[ap]*: select '\\${_.id}' db, version() ver }}\"\ndb\tver\nch-play\t25.5.1.664\nch-altinity\t25.3.3.42\n\n# Using JDBCX as a bridge server (HTTP API for data access)\n$ docker run --rm -d --name bridge -p8080:8080 jdbcx/jdbcx:full server\n$ curl -s -d 'select 2 as num' 'http://localhost:8080/query'\nnum\n2\n$ curl -s -d '{{ db.duckdb-local: select 2 as num }}' 'http://localhost:8080/query'\nnum\n2\n\n# Combining JDBCX driver features with the bridge server for federated querying\n$ curl -s -d \"select * from {{ table.mcp.everything(target=prompt) }}\nwhere name like 'simple%'\" 'http://localhost:8080/query'\nname,description,arguments\nsimple_prompt,A prompt without arguments,\n$ curl -s -d 'select c.name\nfrom {{ table.db.ch-play: show databases }} c\nleft outer join {{ table.db.ch-altinity: show databases }} a\n  on c.name = a.name\nwhere a.name is null' 'http://localhost:8080/query'\nname\nblogs\ngit_clickhouse\nmgbench\n```\n\n## Features\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd\u003e Feature \u003c/td\u003e \u003ctd\u003e Examples \u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e Chained query \u003c/td\u003e\n\u003ctd\u003e\n\n```sql\n-- ask a question(check out ~/.jdbcx/web/baidu-*.properties for details)\n{{ web.baidu-llm(pre.query=web.baidu-auth): who are you? }}\n\n-- get messages of a chat(see ~/.jdbcx/web/m365-*.properties for details)\n{{ web.m365-graph(\n\tpre.query=web.m365-auth,\n\tresult.json.path=value,\n\tm365.api=\"chats/\u003cURL encoded chat ID\u003e/messages?$top=50\")\n}}\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e Dynamic query \u003c/td\u003e\n\u003ctd\u003e\n\n```sql\n-- https://clickhouse.com/docs/en/sql-reference/aggregate-functions/parametric-functions#retention\n{% var(delimiter=;): dates=['2020-01-01','2020-01-02','2020-01-03'] %}\nSELECT\n    uid,\n    retention({{ script: \"date='\" + ${dates}.join(\"',date='\") + \"'\" }}) AS r\nFROM retention_test\nWHERE date IN ({{ script: \"'\" + ${dates}.join(\"','\") + \"'\" }})\nGROUP BY uid\nORDER BY uid ASC\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e Multi-language query \u003c/td\u003e\n\u003ctd\u003e\n\n```sql\n{% var: num=3 %}\nselect {{ script: ${num} - 2 }} one,\n    {{ shell: echo 2 }} two,\n    {{ db.ch-play: select ${num} }} three\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e Query substitution \u003c/td\u003e\n\u003ctd\u003e\n\n```sql\n{% var: func=toYear, sdate='2023-01-01' %}\nSELECT ${func}(create_date) AS d, count(1) AS c\nFROM my_table\nWHERE create_date \u003e= ${sdate}\nGROUP BY d\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e Scripting \u003c/td\u003e\n\u003ctd\u003e\n\n```sql\n-- benchmark on ClickHouse\nselect a[1] `CPU%`, a[2] `MEM(KB)`, a[3] `Elapsed Time(s)`,\n\ta[4] `CPU Time(s)`, a[5] `User Time(s)`, a[6] `Switches`,\n\ta[7] `Waits`, a[8] `File Inputs`, a[9] `File Outputs`, a[10] `Swaps`\nfrom (\nselect splitByChar(',', '{{ shell.myserver(cli.stderr.redirect=true):\n/bin/time -f '%P,%M,%e,%S,%U,%c,%w,%I,%O,%W' du -sh . \u003e /dev/null\n}}') a\n)\n\n-- runtime inspection\n{{ script: helper.table(\n  // fields\n  ['connection_class_loader', 'current_class_loader', 'context_class_loader'],\n  // rows\n  [\n    [\n      Packages.io.github.jdbcx.WrappedDriver.__javaObject__.getClassLoader(),\n      helper.getClass().getClassLoader(),\n      java.lang.Thread.currentThread().getContextClassLoader()\n    ]\n  ]\n)\n}}\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n## Known Issues\n\n| #   | Issue                                     | Workaround                          |\n| --- | ----------------------------------------- | ----------------------------------- |\n| 1   | Query cancellation is not fully supported | avoid query like `{{ shell: top }}` |\n| 2   | Connection pooling is not supported       | -                                   |\n| 3   | Nested query is not supported             | -                                   |\n| 4   | MCP extension requires JDK 17+            | -                                   |\n\n## Security\n\nTo secure datasource credentials, encrypt them with a secret key. This key is typically stored as an encrypted secret file in k8s or docker swarm. Remember, if you rename a datasource, you must re-encrypt its credentials.\n\n```bash\n$ cat mysql1.properties\njdbcx.description=My MySQL server for development.\njdbcx.driver=com.mysql.cj.jdbc.Driver\njdbcx.url=jdbc:mysql://localhost:3306\nuser=root\npassword=\u003cmy root password\u003e\n\n# Generate secret key\n$ docker run --rm -it jdbcx/jdbcx keygen \u003e secret.key\n\n# Use the secret key to encrypt password for specific datasource\n$ docker run --rm -it -v `pwd`/secret.key:/app/.jdbcx/secret.key jdbcx/jdbcx encrypt '\u003cmy root password\u003e' 'mysql1'\nGm7+r5vldBu+irReosAWUosbWhNWpiYaocmspi5oeRK/tLsNH0U/zUp7jDmAqGQ=\n\n# Verify the encrypted password\n$ docker run --rm -it -v `pwd`/secret.key:/app/.jdbcx/secret.key jdbcx/jdbcx decrypt 'Gm7+r5vldBu+irReosAWUosbWhNWpiYaocmspi5oeRK/tLsNH0U/zUp7jDmAqGQ=' 'mysql1'\n\u003cmy root password\u003e\n\n# Update datasource configuration to use encrypted password\n$ sed -i .bak 's|^\\(password\\)=.*|\\1.encrypted=Gm7+r5vldBu+irReosAWUosbWhNWpiYaocmspi5oeRK/tLsNH0U/zUp7jDmAqGQ=|' mysql1.properties\n$ cat mysql1.properties\njdbcx.description=My MySQL server for development.\njdbcx.driver=com.mysql.cj.jdbc.Driver\njdbcx.url=jdbc:mysql://localhost:3306\nuser=root\npassword.encrypted=Gm7+r5vldBu+irReosAWUosbWhNWpiYaocmspi5oeRK/tLsNH0U/zUp7jDmAqGQ=\n\n# Test the encrypted datasource\n$ docker run --rm -i -d -p8080:8080 -v `pwd`/secret.key:/app/.jdbcx/secret.key jdbcx/jdbcx -v `pwd`/mysql1.properties:/app/.jdbcx/db/mysql1.properties server\n$ curl -s -d 'select * from {{table.db.mysql1: show processlist}}' 'http://localhost:8080/query'\n```\n\nFor server authentication, please refer to [here](server/README.md#authentication).\n\n## Performance\n\n### Test Environment\n\n- JDK: openjdk version \"17.0.7\" 2023-04-18\n- Tool: Apache JMeter 5.6.2\n- Database: ClickHouse 22.8\n- JDBC Driver: clickhouse-jdbc v0.4.6\n\n### Test Configuration\n\n- Concurrent Users: 20\n- Loop Count: 1000\n- Connection Pool:\n  - Size: 30\n  - Init SQL and Validation Query are identical\n\n### Test Results\n\n| Connection        | Init SQL                                     | Test Query                                       | Avg Response Time (ms) | Max Response Time (ms) | Throughput (qps) |\n| ----------------- | -------------------------------------------- | ------------------------------------------------ | ---------------------- | ---------------------- | ---------------- |\n| `jdbc:ch`         | select \\* from system.numbers limit 1        | select \\* from system.numbers limit 50000        | 69                     | 815                    | 279.87           |\n| `jdbcx:ch`        | select \\* from system.numbers limit 1        | select \\* from system.numbers limit 50000        | 71                     | 891                    | 272.99           |\n| `jdbcx:script:ch` | 'select \\* from system.numbers limit 1'      | 'select \\* from system.numbers limit ' + 50000   | 72                     | 1251                   | 270.65           |\n| `jdbcx:shell:ch`  | echo 'select \\* from system.numbers limit 1' | echo 'select \\* from system.numbers limit 50000' | 91                     | 650                    | 214.45           |\n| `jdbcx:prql:ch`   | from \\`system.numbers\\` \\| take 1            | from \\`system.numbers\\` \\| take 50000            | 106                    | 1103                   | 184.27           |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdbcx%2Fjdbcx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjdbcx%2Fjdbcx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdbcx%2Fjdbcx/lists"}