From 33384dfdc5f26a5615db26329d78a9d4e3b666bd Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Mon, 2 Dec 2024 18:30:22 +0800 Subject: [PATCH 01/17] feat(ci): add publish docker --- .github/workflows/publish-docker.yml | 3 +- client/datacap-cli/pom.xml | 2 +- configure/etc/bin/install-plugin.sh | 2 +- configure/etc/conf/application.properties | 2 +- configure/metadata.json | 268 +++++++++--------- configure/publish/publish-docker.sh | 80 ++++++ convert/datacap-convert-csv/pom.xml | 2 +- convert/datacap-convert-json/pom.xml | 2 +- convert/datacap-convert-none/pom.xml | 2 +- convert/datacap-convert-spi/pom.xml | 2 +- convert/datacap-convert-txt/pom.xml | 2 +- convert/datacap-convert-xml/pom.xml | 2 +- core/datacap-captcha/pom.xml | 2 +- core/datacap-common/pom.xml | 2 +- core/datacap-parser/pom.xml | 2 +- core/datacap-plugin/pom.xml | 2 +- core/datacap-security/pom.xml | 2 +- core/datacap-server/pom.xml | 2 +- core/datacap-service/pom.xml | 2 +- core/datacap-spi/pom.xml | 2 +- core/datacap-sql/pom.xml | 2 +- core/datacap-ui/package.json | 2 +- docs/docs/release/latest.en.md | 3 +- driver/datacap-driver-mongo/pom.xml | 2 +- driver/datacap-driver-redis/pom.xml | 2 +- executor/datacap-executor-local/pom.xml | 2 +- executor/datacap-executor-seatunnel/pom.xml | 2 +- executor/datacap-executor-spi/pom.xml | 2 +- fs/datacap-fs-alioss/pom.xml | 2 +- fs/datacap-fs-amazon-s3/pom.xml | 2 +- fs/datacap-fs-local/pom.xml | 2 +- fs/datacap-fs-minio/pom.xml | 2 +- fs/datacap-fs-qiniu/pom.xml | 2 +- fs/datacap-fs-spi/pom.xml | 2 +- fs/datacap-fs-tencent-cos/pom.xml | 2 +- lib/datacap-http/pom.xml | 2 +- lib/datacap-logger/pom.xml | 2 +- lib/datacap-schedule/pom.xml | 2 +- lib/datacap-shell/pom.xml | 2 +- notify/datacap-notify-dingtalk/pom.xml | 2 +- notify/datacap-notify-spi/pom.xml | 2 +- parser/datacap-parser-mysql/pom.xml | 2 +- parser/datacap-parser-spi/pom.xml | 2 +- parser/datacap-parser-trino/pom.xml | 2 +- plugin/datacap-plugin-alioss/pom.xml | 2 +- plugin/datacap-plugin-cassandra/pom.xml | 2 +- plugin/datacap-plugin-ceresdb/pom.xml | 2 +- plugin/datacap-plugin-clickhouse-http/pom.xml | 2 +- plugin/datacap-plugin-clickhouse/pom.xml | 2 +- plugin/datacap-plugin-cratedb-http/pom.xml | 2 +- plugin/datacap-plugin-cratedb/pom.xml | 2 +- plugin/datacap-plugin-db2/pom.xml | 2 +- plugin/datacap-plugin-dm/pom.xml | 2 +- plugin/datacap-plugin-doris/pom.xml | 2 +- plugin/datacap-plugin-dremio/pom.xml | 2 +- plugin/datacap-plugin-druid/pom.xml | 2 +- plugin/datacap-plugin-duckdb/pom.xml | 2 +- .../datacap-plugin-elasticsearch-8x/pom.xml | 2 +- plugin/datacap-plugin-greptimedb/pom.xml | 2 +- plugin/datacap-plugin-h2-tcp/pom.xml | 2 +- plugin/datacap-plugin-h2/pom.xml | 2 +- plugin/datacap-plugin-hdfs/pom.xml | 2 +- plugin/datacap-plugin-hive-2x/pom.xml | 2 +- plugin/datacap-plugin-hologres/pom.xml | 2 +- plugin/datacap-plugin-ignite/pom.xml | 2 +- plugin/datacap-plugin-impala/pom.xml | 2 +- plugin/datacap-plugin-influxdb/pom.xml | 2 +- plugin/datacap-plugin-iotdb/pom.xml | 2 +- plugin/datacap-plugin-kafka/pom.xml | 2 +- plugin/datacap-plugin-kylin/pom.xml | 2 +- plugin/datacap-plugin-kyuubi/pom.xml | 2 +- plugin/datacap-plugin-matrixone/pom.xml | 2 +- plugin/datacap-plugin-monetdb/pom.xml | 2 +- plugin/datacap-plugin-mongo-atlas/pom.xml | 2 +- plugin/datacap-plugin-mongo-community/pom.xml | 2 +- plugin/datacap-plugin-mysql/pom.xml | 2 +- plugin/datacap-plugin-neo4j/pom.xml | 2 +- plugin/datacap-plugin-oceanbase/pom.xml | 2 +- plugin/datacap-plugin-oracle/pom.xml | 2 +- plugin/datacap-plugin-paradedb/pom.xml | 2 +- plugin/datacap-plugin-phoenix/pom.xml | 2 +- plugin/datacap-plugin-pinot/pom.xml | 2 +- plugin/datacap-plugin-postgresql/pom.xml | 2 +- plugin/datacap-plugin-presto/pom.xml | 2 +- plugin/datacap-plugin-questdb/pom.xml | 2 +- plugin/datacap-plugin-redis-jdbc/pom.xml | 2 +- plugin/datacap-plugin-redis/pom.xml | 2 +- plugin/datacap-plugin-scylladb/pom.xml | 2 +- plugin/datacap-plugin-snowflake/pom.xml | 2 +- plugin/datacap-plugin-solr/pom.xml | 2 +- plugin/datacap-plugin-sqlserver/pom.xml | 2 +- plugin/datacap-plugin-starrocks/pom.xml | 2 +- plugin/datacap-plugin-tdengine/pom.xml | 2 +- plugin/datacap-plugin-timescale/pom.xml | 2 +- plugin/datacap-plugin-trino/pom.xml | 2 +- plugin/datacap-plugin-ydb/pom.xml | 2 +- plugin/datacap-plugin-zookeeper/pom.xml | 2 +- pom.xml | 2 +- scheduler/datacap-scheduler-local/pom.xml | 2 +- scheduler/datacap-scheduler-spi/pom.xml | 2 +- shaded/datacap-shaded-neo4j/pom.xml | 2 +- shaded/datacap-shaded-pinot/pom.xml | 2 +- shaded/datacap-shaded-ydb/pom.xml | 2 +- test/datacap-test-convert/pom.xml | 2 +- test/datacap-test-core/pom.xml | 2 +- test/datacap-test-executor/pom.xml | 2 +- test/datacap-test-fs/pom.xml | 2 +- test/datacap-test-lib/pom.xml | 2 +- test/datacap-test-plugin/pom.xml | 2 +- test/datacap-test-scheduler/pom.xml | 2 +- 110 files changed, 323 insertions(+), 243 deletions(-) create mode 100644 configure/publish/publish-docker.sh diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml index 9068d2fd1a..5bf457cdaa 100644 --- a/.github/workflows/publish-docker.yml +++ b/.github/workflows/publish-docker.yml @@ -36,6 +36,7 @@ jobs: chmod 755 ./mvnw ./mvnw clean install package -Dspotbugs.skip -Dgpg.skip -Dcheckstyle.skip -DskipTests=true -q + - name: Cache binary id: cache-binary uses: actions/cache@v3 @@ -44,7 +45,7 @@ jobs: with: path: | ./Dockerfile - ./dist/datacap-server-${{ needs.before-compile.outputs.APP_VERSION }}-bin.tar.gz + ./dist/datacap-server-${{ steps.apply_version.outputs.APP_VERSION }}-bin.tar.gz key: ${{ runner.os }}-build-${{ env.cache-name }} restore-keys: ${{ runner.os }}-build-${{ env.cache-name }} diff --git a/client/datacap-cli/pom.xml b/client/datacap-cli/pom.xml index 8e4270ec0d..eea2dff8c0 100644 --- a/client/datacap-cli/pom.xml +++ b/client/datacap-cli/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/configure/etc/bin/install-plugin.sh b/configure/etc/bin/install-plugin.sh index 5d7c639015..0e50b68e9b 100644 --- a/configure/etc/bin/install-plugin.sh +++ b/configure/etc/bin/install-plugin.sh @@ -1,7 +1,7 @@ #!/bin/sh HOME=$(pwd) -VERSION=2024.4.0 +VERSION=2024.4.1-SNAPSHOT CDN_CENTER="https://repo1.maven.org/maven2/io/edurt/datacap" install_package() { diff --git a/configure/etc/conf/application.properties b/configure/etc/conf/application.properties index 730082c139..e143a29af4 100644 --- a/configure/etc/conf/application.properties +++ b/configure/etc/conf/application.properties @@ -1,5 +1,5 @@ ################################### Banner configure ################################# -app.version=2024.4.0 +app.version=2024.4.1-SNAPSHOT ################################### Basic configure ################################# server.port=9096 diff --git a/configure/metadata.json b/configure/metadata.json index 2864eaab4d..231002d400 100644 --- a/configure/metadata.json +++ b/configure/metadata.json @@ -10,10 +10,10 @@ "description": "A powerful MySQL integration plugin that provides comprehensive database connectivity. Features include table/view management, data import/export, SQL query execution, stored procedure support, and real-time data synchronization. Optimized for high-performance data operations with connection pooling and batch processing capabilities.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/mysql.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "8.0", "5.7" @@ -26,10 +26,10 @@ "description": "ClickHouse is a distributed column-oriented database. It is a distributed database with a focus on performance, scalability, and ease of use.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/clickhouse.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -41,10 +41,10 @@ "description": "InfluxDB is a time series database that stores and retrieves data points. It is a distributed database with a focus on performance, scalability, and ease of use.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/influxdb.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -56,10 +56,10 @@ "description": "Solr is highly reliable, scalable and fault tolerant, providing distributed indexing, replication and load-balanced querying, automated failover and recovery, centralized configuration and more. Solr powers the search and navigation features of many of the world's largest internet sites.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/solr.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -71,10 +71,10 @@ "description": "CrateDB is a hyper-fast database for real-time analytics and hybrid search. It handles multiple types of data and combines the simplicity of SQL with the scalability of a distributed architecture.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/cratedb.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -86,10 +86,10 @@ "description": "Use HTTP to access the remote CrateDB database", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/cratedbhttp.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -101,10 +101,10 @@ "description": "Zookeeper is a distributed, distributed configuration service. It is a distributed database with a focus on performance, scalability, and ease of use.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/zookeeper.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -116,10 +116,10 @@ "description": "Apache Kafka is an open-source distributed event streaming platform used by thousands of companies for high-performance data pipelines, streaming analytics, data integration, and mission-critical applications.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/kafka.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -131,10 +131,10 @@ "description": "Redis is an in-memory data store used by millions of developers as a cache, vector database, document database, streaming engine, and message broker. Redis has built-in replication and different levels of on-disk persistence. It supports complex data types (for example, strings, hashes, lists, sets, sorted sets, and JSON), with atomic operations defined on those data types.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/redis.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -146,10 +146,10 @@ "description": "H2 is a small, fast, and easy-to-use in-memory database.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/h2.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -161,10 +161,10 @@ "description": "IBM® Db2® is the cloud-native database built to power low-latency transactions, real-time analytics and AI applications at scale.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/db2.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -176,10 +176,10 @@ "description": "A professional database software developer and service provider, we provide users with technically advanced and detailed products.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/dm.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -191,10 +191,10 @@ "description": "Hadoop Distributed File System (HDFS) is a distributed file system based on the Hadoop project.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/hdfs.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -206,10 +206,10 @@ "description": "Ali OSS is a cloud storage service that provides a simple, secure and efficient way to store and manage data.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/alioss.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -221,10 +221,10 @@ "description": "Dremio is a free, open source, distributed data platform.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/dremio.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -236,10 +236,10 @@ "description": "A high performance, real-time analytics database that delivers sub-second queries on streaming and batch data at scale and under load.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/druid.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -251,10 +251,10 @@ "description": "To use DuckDB, you must first create a connection to a database. The exact syntax varies between the client APIs but it typically involves passing an argument to configure persistence.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/duckdb.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -266,10 +266,10 @@ "description": "Apache Pinot is a real-time distributed OLAP datastore, built to deliver scalable real-time analytics with low latency. It can ingest from batch data sources (such as Hadoop HDFS, Amazon S3, Azure ADLS, Google Cloud Storage) as well as stream data sources (such as Apache Kafka).", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/pinot.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -281,10 +281,10 @@ "description": "Cassandra is a distributed key-value store for the cloud.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/cassandra.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -296,10 +296,10 @@ "description": "MatrixOne is a hyper-converged cloud & edge native distributed database with a structure that separates storage, computation, and transactions to form a consolidated HSTAP data engine. This engine enables a single database system to accommodate diverse business loads such as OLTP, OLAP, and stream computing. It also supports deployment and utilization across public, private, and edge clouds, ensuring compatibility with diverse infrastructures.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/matrixone.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -311,10 +311,10 @@ "description": "ScyllaDB is a distributed database written in C++ and designed to fully exploit modern cloud infrastructure. It utilizes a shard-per-core architecture, meaning each CPU core has dedicated resources that independently handle data for maximum efficiency. ", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/scylladb.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -326,10 +326,10 @@ "description": "ParadeDB is a modern Elasticsearch alternative built on Postgres. Built for real-time, update-heavy workloads.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/paradedb.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -341,10 +341,10 @@ "description": "The Apache Hive ™ is a distributed, fault-tolerant data warehouse system that enables analytics at a massive scale and facilitates reading, writing, and managing petabytes of data residing in distributed storage using SQL.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/hive2x.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "2.x" ], @@ -356,10 +356,10 @@ "description": "Apache Kyuubi, a distributed and multi-tenant gateway to provide serverless SQL on lakehouses.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/kyuubi.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -371,10 +371,10 @@ "description": "Apache Ignite is a distributed database for high-performance computing with in-memory speed.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/ignite.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -386,10 +386,10 @@ "description": "Apache Impala is the open source, native analytic database for open data and table formats.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/impala.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -401,10 +401,10 @@ "description": "Apache Kylin is a leading open source OLAP engine for Big Data capable for sub-second query latency on trillions of records. Since being created and open sourced by eBay in 2014, and graduated to Top Level Project of Apache Software Foundation in 2015. Kylin has quickly been adopted by thousands of organizations world widely as their critical analytics application for Big Data.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/kylin.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -416,10 +416,10 @@ "description": "TimescaleDB is an open-source database designed to make SQL scalable for time-series data. It is engineered up from PostgreSQL and packaged as a PostgreSQL extension, providing automatic partitioning across time and space (partitioning key), as well as full SQL support.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/timescale.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -431,10 +431,10 @@ "description": "Apache IoTDB (Database for Internet of Things) is an IoT native database with high performance for data management and analysis, deployable on the edge and the cloud. ", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/iotdb.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -446,10 +446,10 @@ "description": "MonetDB is a high performance relational database system for analytics.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/monetdb.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -461,10 +461,10 @@ "description": "YDB is a versatile open source Distributed SQL Database that combines high availability and scalability with strong consistency and ACID transactions. It accommodates transactional (OLTP), analytical (OLAP), and streaming workloads simultaneously.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/ydb.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -476,10 +476,10 @@ "description": "Neo4j is a graph database for knowledge management and analysis.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/neo4j.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -491,10 +491,10 @@ "description": "OceanBase is an enterprise distributed relational database with high availability, high performance, horizontal scalability, and compatibility with SQL standards.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/oceanbase.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -506,10 +506,10 @@ "description": "Oracle is an advanced, enterprise-class relational database management system.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/oracle.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -521,10 +521,10 @@ "description": "Apache Phoenix is a SQL skin over HBase delivered as a client-embedded JDBC driver targeting low latency queries over HBase data. ", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/phoenix.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -536,10 +536,10 @@ "description": "PostgreSQL is a powerful, open source object-relational database system.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/postgresql.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -551,10 +551,10 @@ "description": "Presto is a distributed SQL query engine for big data.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/presto.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -566,10 +566,10 @@ "description": "Snowflake is a database for analytics.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/snowflake.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -581,10 +581,10 @@ "description": "Microsoft SQL Server is a relational database management system.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/sqlserver.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -596,10 +596,10 @@ "description": "TDengine is an open source, high-performance, cloud native time-series database optimized for Internet of Things (IoT), Connected Cars, and Industrial IoT.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/tdengine.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -611,10 +611,10 @@ "description": "Trino is a distributed SQL query engine for big data.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/trino.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -626,10 +626,10 @@ "description": "Apache Doris is a distributed OLAP database.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/doris.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -641,10 +641,10 @@ "description": "StarRocks is a distributed OLAP database.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/starrocks.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -656,10 +656,10 @@ "description": "Hologres is a unified real-time data warehousing service developed by Alibaba Cloud. You can use Hologres to write, update, process, and analyze large amounts of data in real time.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/hologres.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -671,10 +671,10 @@ "description": "GreptimeDB is an open-source unified & cost-effective time-series database for Metrics, Logs, and Events (also Traces in plan). You can gain real-time insights from Edge to Cloud at Any Scale.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/greptimedb.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -686,10 +686,10 @@ "description": "QuestDB is the world's fastest growing open-source time-series database. It offers massive ingestion throughput, millisecond queries, powerful time-series SQL extensions, and scales well with minimal and maximal hardware. Save costs with better performance and efficiency.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/questdb.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -701,10 +701,10 @@ "description": "Use TCP to access the remote H2 database", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/h2tcp.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -716,10 +716,10 @@ "description": "Use HTTP to access the remote ClickHouse database", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/clickhousehttp.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -731,10 +731,10 @@ "description": "CeresDB is a database system designed to allow for the storage and retrieval of semi-structured data, i.e. data that conforms to a “top-level schema” where columns types are known, but those columns can in-turn contain dictionaries or lists.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/ceresdb.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -746,10 +746,10 @@ "description": "Use JDBC to access Redis", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/redisjdbc.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -761,10 +761,10 @@ "description": "Use Elasticsearch 8.x", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/elasticsearch8x.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "8.x" ], @@ -776,10 +776,10 @@ "description": "The MongoDB Atlas SQL JDBC Driver provides SQL connectivity to MongoDB Atlas for client applications developed in Java.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/mongoatlas.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -791,10 +791,10 @@ "description": "The MongoDB Community SQL JDBC Driver provides SQL connectivity to MongoDB Community for client applications developed in Java.", "i18nFormat": true, "type": "Connector", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/mongocommunity.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -806,10 +806,10 @@ "description": "A CSV file conversion plugin for DataCap.", "i18nFormat": true, "type": "Converter", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/convert/csv.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -821,10 +821,10 @@ "description": "A TXT file conversion plugin for DataCap.", "i18nFormat": true, "type": "Converter", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/convert/txt.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -836,10 +836,10 @@ "description": "A JSON file conversion plugin for DataCap.", "i18nFormat": true, "type": "Converter", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/convert/json.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -851,10 +851,10 @@ "description": "A XML file conversion plugin for DataCap.", "i18nFormat": true, "type": "Converter", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/convert/xml.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -866,10 +866,10 @@ "description": "A multidimensional arrays file conversion plugin for DataCap.", "i18nFormat": true, "type": "Converter", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/convert/none.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -881,10 +881,10 @@ "description": "A local execution plugin for DataCap.", "i18nFormat": true, "type": "Executor", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/executor/local.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -896,10 +896,10 @@ "description": "A Seatunnel execution plugin for DataCap.", "i18nFormat": true, "type": "Executor", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/executor/seatunnel.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -911,10 +911,10 @@ "description": "A local scheduling plugin for DataCap.", "i18nFormat": true, "type": "Scheduler", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/scheduler/local.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -926,10 +926,10 @@ "description": "A local file system plugin for DataCap.", "i18nFormat": true, "type": "FileSystem", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/fs/local.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -941,10 +941,10 @@ "description": "A Qiniu file system plugin for DataCap.", "i18nFormat": true, "type": "FileSystem", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/fs/qiniu.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -956,10 +956,10 @@ "description": "A Ali OSS file system plugin for DataCap.", "i18nFormat": true, "type": "FileSystem", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/fs/alioss.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -971,10 +971,10 @@ "description": "A Tencent COS file system plugin for DataCap.", "i18nFormat": true, "type": "FileSystem", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/fs/tencent-cos.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -986,10 +986,10 @@ "description": "A Amazon S3 file system plugin for DataCap.", "i18nFormat": true, "type": "FileSystem", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/fs/amazon-s3.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], @@ -1001,10 +1001,10 @@ "description": "A Minio file system plugin for DataCap.", "i18nFormat": true, "type": "FileSystem", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/fs/minio.svg", - "released": "2024-12-02 16:45:07", + "released": "2024-12-02 18:29:41", "supportVersion": [ "ALL" ], diff --git a/configure/publish/publish-docker.sh b/configure/publish/publish-docker.sh new file mode 100644 index 0000000000..ad29330f0a --- /dev/null +++ b/configure/publish/publish-docker.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +# Check if Docker is installed and running +# 检查 Docker 是否已安装并正在运行 +if ! command -v docker &> /dev/null; then + echo "Error: Docker is not installed" + echo "错误:Docker 未安装" + exit 1 +fi + +# Check if Docker daemon is running +# 检查 Docker 守护进程是否运行 +if ! docker info &> /dev/null; then + echo "Error: Docker daemon is not running" + echo "错误:Docker 守护进程未运行" + exit 1 +fi + +# Check if Docker buildx is available +# 检查 Docker buildx 是否可用 +if ! docker buildx version &> /dev/null; then + echo "Error: Docker buildx is not available" + echo "错误:Docker buildx 不可用" + exit 1 +fi + +# Get Maven project version +# 获取 Maven 项目版本号 +APP_VERSION=`./mvnw -Dexec.executable='echo' -Dexec.args='${project.version}' --non-recursive exec:exec -Dorg.slf4j.simpleLogger.defaultLogLevel=WARN -Dorg.slf4j.simpleLogger.log.org.apache.maven.plugins.help=INFO | tail -1` + +# Check if version was successfully retrieved +# 检查版本号是否成功获取 +if [ -z "$APP_VERSION" ]; then + echo "Error: Failed to get application version" + echo "错误:获取应用版本失败" + exit 1 +fi + +# Print the version that will be used +# 打印将要使用的版本号 +echo "Building version: ${APP_VERSION}" +echo "构建版本:${APP_VERSION}" + +# Create and use a new builder instance +# 创建并使用新的构建器实例 +echo "Setting up Docker buildx..." +echo "设置 Docker buildx..." +docker buildx create --use + +# Check if Dockerfile exists +# 检查 Dockerfile 是否存在 +if [ ! -f "Dockerfile" ]; then + echo "Error: Dockerfile not found" + echo "错误:未找到 Dockerfile" + exit 1 +fi + +# Build multi-architecture images and push to Docker Hub +# - Platform: linux/amd64 (Intel/AMD) and linux/arm64 (ARM) +# - Tags: version specific and latest +# 构建多架构镜像并推送到 Docker Hub +# - 平台: linux/amd64 (Intel/AMD) 和 linux/arm64 (ARM) +# - 标签: 特定版本和最新版 +echo "Building and pushing Docker images..." +echo "构建并推送 Docker 镜像..." +if docker buildx build --platform linux/amd64,linux/arm64 \ + -t devliveorg/datacap:${APP_VERSION} \ + -t devliveorg/datacap:latest \ + . --push; then + # Print success message + # 打印成功信息 + echo "Successfully built and pushed images:" + echo "成功构建并推送以下镜像:" + echo "- devliveorg/datacap:${APP_VERSION}" + echo "- devliveorg/datacap:latest" +else + echo "Error: Failed to build and push Docker images" + echo "错误:构建并推送 Docker 镜像失败" + exit 1 +fi \ No newline at end of file diff --git a/convert/datacap-convert-csv/pom.xml b/convert/datacap-convert-csv/pom.xml index 5df3b33a7b..82fb7c4bec 100644 --- a/convert/datacap-convert-csv/pom.xml +++ b/convert/datacap-convert-csv/pom.xml @@ -5,7 +5,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/convert/datacap-convert-json/pom.xml b/convert/datacap-convert-json/pom.xml index 217f84adeb..e2fc99a390 100644 --- a/convert/datacap-convert-json/pom.xml +++ b/convert/datacap-convert-json/pom.xml @@ -5,7 +5,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/convert/datacap-convert-none/pom.xml b/convert/datacap-convert-none/pom.xml index 3bc772ca95..649c46bf60 100644 --- a/convert/datacap-convert-none/pom.xml +++ b/convert/datacap-convert-none/pom.xml @@ -5,7 +5,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/convert/datacap-convert-spi/pom.xml b/convert/datacap-convert-spi/pom.xml index 667adfd1ec..2f14463e4c 100644 --- a/convert/datacap-convert-spi/pom.xml +++ b/convert/datacap-convert-spi/pom.xml @@ -5,7 +5,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/convert/datacap-convert-txt/pom.xml b/convert/datacap-convert-txt/pom.xml index 11dd9e66ca..bfaa03bc9c 100644 --- a/convert/datacap-convert-txt/pom.xml +++ b/convert/datacap-convert-txt/pom.xml @@ -5,7 +5,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/convert/datacap-convert-xml/pom.xml b/convert/datacap-convert-xml/pom.xml index 201aa23928..24d64984f3 100644 --- a/convert/datacap-convert-xml/pom.xml +++ b/convert/datacap-convert-xml/pom.xml @@ -5,7 +5,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/core/datacap-captcha/pom.xml b/core/datacap-captcha/pom.xml index a52f4b99ee..a275a96055 100644 --- a/core/datacap-captcha/pom.xml +++ b/core/datacap-captcha/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/core/datacap-common/pom.xml b/core/datacap-common/pom.xml index 55222e67cc..9f3747687d 100644 --- a/core/datacap-common/pom.xml +++ b/core/datacap-common/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/core/datacap-parser/pom.xml b/core/datacap-parser/pom.xml index 936a6e720d..0a67635853 100644 --- a/core/datacap-parser/pom.xml +++ b/core/datacap-parser/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/core/datacap-plugin/pom.xml b/core/datacap-plugin/pom.xml index 5e84068948..4e8fbde2d7 100644 --- a/core/datacap-plugin/pom.xml +++ b/core/datacap-plugin/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/core/datacap-security/pom.xml b/core/datacap-security/pom.xml index 14debfbf35..01ae7308f7 100644 --- a/core/datacap-security/pom.xml +++ b/core/datacap-security/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/core/datacap-server/pom.xml b/core/datacap-server/pom.xml index 00e4010761..db69e0f4b5 100644 --- a/core/datacap-server/pom.xml +++ b/core/datacap-server/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/core/datacap-service/pom.xml b/core/datacap-service/pom.xml index 8c8263c60d..6872fa387b 100644 --- a/core/datacap-service/pom.xml +++ b/core/datacap-service/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/core/datacap-spi/pom.xml b/core/datacap-spi/pom.xml index 5d6193e7b7..8de62ecd8f 100644 --- a/core/datacap-spi/pom.xml +++ b/core/datacap-spi/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/core/datacap-sql/pom.xml b/core/datacap-sql/pom.xml index d73b031bc0..44d449b21f 100644 --- a/core/datacap-sql/pom.xml +++ b/core/datacap-sql/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/core/datacap-ui/package.json b/core/datacap-ui/package.json index 2d77efc161..db14c0d011 100644 --- a/core/datacap-ui/package.json +++ b/core/datacap-ui/package.json @@ -1,7 +1,7 @@ { "name": "datacap-ui", "description": "DataCap console", - "version": "2024.4.0", + "version": "2024.4.1-SNAPSHOT", "private": true, "scripts": { "dev": "vite", diff --git a/docs/docs/release/latest.en.md b/docs/docs/release/latest.en.md index 348218fb03..de38e8d309 100644 --- a/docs/docs/release/latest.en.md +++ b/docs/docs/release/latest.en.md @@ -24,5 +24,4 @@ This is a brand new version that uses a new plugin management system, new APIs, --- -- Added Open API documentation -- \ No newline at end of file +- Added Open API documentation \ No newline at end of file diff --git a/driver/datacap-driver-mongo/pom.xml b/driver/datacap-driver-mongo/pom.xml index 317be37d4c..f0debc95d7 100644 --- a/driver/datacap-driver-mongo/pom.xml +++ b/driver/datacap-driver-mongo/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/driver/datacap-driver-redis/pom.xml b/driver/datacap-driver-redis/pom.xml index e9e28557c8..097cbe64f6 100644 --- a/driver/datacap-driver-redis/pom.xml +++ b/driver/datacap-driver-redis/pom.xml @@ -6,7 +6,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/executor/datacap-executor-local/pom.xml b/executor/datacap-executor-local/pom.xml index 10abf20930..84b455dbfb 100644 --- a/executor/datacap-executor-local/pom.xml +++ b/executor/datacap-executor-local/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/executor/datacap-executor-seatunnel/pom.xml b/executor/datacap-executor-seatunnel/pom.xml index bd433e705b..c4c01bf981 100644 --- a/executor/datacap-executor-seatunnel/pom.xml +++ b/executor/datacap-executor-seatunnel/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/executor/datacap-executor-spi/pom.xml b/executor/datacap-executor-spi/pom.xml index d8828f1e96..0edbf1a85b 100644 --- a/executor/datacap-executor-spi/pom.xml +++ b/executor/datacap-executor-spi/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/fs/datacap-fs-alioss/pom.xml b/fs/datacap-fs-alioss/pom.xml index 767f518da2..1d50110e00 100644 --- a/fs/datacap-fs-alioss/pom.xml +++ b/fs/datacap-fs-alioss/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/fs/datacap-fs-amazon-s3/pom.xml b/fs/datacap-fs-amazon-s3/pom.xml index d58400015d..b4feb1356f 100644 --- a/fs/datacap-fs-amazon-s3/pom.xml +++ b/fs/datacap-fs-amazon-s3/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/fs/datacap-fs-local/pom.xml b/fs/datacap-fs-local/pom.xml index 3e849f9c07..aa1ba41fe3 100644 --- a/fs/datacap-fs-local/pom.xml +++ b/fs/datacap-fs-local/pom.xml @@ -3,7 +3,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/fs/datacap-fs-minio/pom.xml b/fs/datacap-fs-minio/pom.xml index ebfef8fec9..42b9dc5dbd 100644 --- a/fs/datacap-fs-minio/pom.xml +++ b/fs/datacap-fs-minio/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/fs/datacap-fs-qiniu/pom.xml b/fs/datacap-fs-qiniu/pom.xml index a8c98f3a22..c9416e484d 100644 --- a/fs/datacap-fs-qiniu/pom.xml +++ b/fs/datacap-fs-qiniu/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/fs/datacap-fs-spi/pom.xml b/fs/datacap-fs-spi/pom.xml index af5984d2a1..a5850c1ca7 100644 --- a/fs/datacap-fs-spi/pom.xml +++ b/fs/datacap-fs-spi/pom.xml @@ -3,7 +3,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/fs/datacap-fs-tencent-cos/pom.xml b/fs/datacap-fs-tencent-cos/pom.xml index 7d26ca6e48..fbc58e624d 100644 --- a/fs/datacap-fs-tencent-cos/pom.xml +++ b/fs/datacap-fs-tencent-cos/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/lib/datacap-http/pom.xml b/lib/datacap-http/pom.xml index 73e745f396..4d2664a4c1 100644 --- a/lib/datacap-http/pom.xml +++ b/lib/datacap-http/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/lib/datacap-logger/pom.xml b/lib/datacap-logger/pom.xml index 595ec05d35..871f589fd0 100644 --- a/lib/datacap-logger/pom.xml +++ b/lib/datacap-logger/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/lib/datacap-schedule/pom.xml b/lib/datacap-schedule/pom.xml index 9f0f500e71..d6d577078f 100644 --- a/lib/datacap-schedule/pom.xml +++ b/lib/datacap-schedule/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/lib/datacap-shell/pom.xml b/lib/datacap-shell/pom.xml index 3bb03912bf..4700590da1 100644 --- a/lib/datacap-shell/pom.xml +++ b/lib/datacap-shell/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/notify/datacap-notify-dingtalk/pom.xml b/notify/datacap-notify-dingtalk/pom.xml index 1e7f5c743f..b13836e147 100644 --- a/notify/datacap-notify-dingtalk/pom.xml +++ b/notify/datacap-notify-dingtalk/pom.xml @@ -5,7 +5,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/notify/datacap-notify-spi/pom.xml b/notify/datacap-notify-spi/pom.xml index a1205e2b49..b217779a68 100644 --- a/notify/datacap-notify-spi/pom.xml +++ b/notify/datacap-notify-spi/pom.xml @@ -5,7 +5,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/parser/datacap-parser-mysql/pom.xml b/parser/datacap-parser-mysql/pom.xml index 55c4d038c0..fe1eb9c24a 100644 --- a/parser/datacap-parser-mysql/pom.xml +++ b/parser/datacap-parser-mysql/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/parser/datacap-parser-spi/pom.xml b/parser/datacap-parser-spi/pom.xml index e6db254e90..22729ab176 100644 --- a/parser/datacap-parser-spi/pom.xml +++ b/parser/datacap-parser-spi/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/parser/datacap-parser-trino/pom.xml b/parser/datacap-parser-trino/pom.xml index 12a596c0aa..8b2f43afc3 100644 --- a/parser/datacap-parser-trino/pom.xml +++ b/parser/datacap-parser-trino/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-alioss/pom.xml b/plugin/datacap-plugin-alioss/pom.xml index 0adcf56993..f83665a5c5 100644 --- a/plugin/datacap-plugin-alioss/pom.xml +++ b/plugin/datacap-plugin-alioss/pom.xml @@ -6,7 +6,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-cassandra/pom.xml b/plugin/datacap-plugin-cassandra/pom.xml index 468c67fe8f..8cced68c98 100644 --- a/plugin/datacap-plugin-cassandra/pom.xml +++ b/plugin/datacap-plugin-cassandra/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-ceresdb/pom.xml b/plugin/datacap-plugin-ceresdb/pom.xml index 7b99b18a0d..864c225083 100644 --- a/plugin/datacap-plugin-ceresdb/pom.xml +++ b/plugin/datacap-plugin-ceresdb/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-clickhouse-http/pom.xml b/plugin/datacap-plugin-clickhouse-http/pom.xml index c9505de1e6..5e87dd178d 100644 --- a/plugin/datacap-plugin-clickhouse-http/pom.xml +++ b/plugin/datacap-plugin-clickhouse-http/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-clickhouse/pom.xml b/plugin/datacap-plugin-clickhouse/pom.xml index 4f84a62f15..5067526b6b 100644 --- a/plugin/datacap-plugin-clickhouse/pom.xml +++ b/plugin/datacap-plugin-clickhouse/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-cratedb-http/pom.xml b/plugin/datacap-plugin-cratedb-http/pom.xml index c3b4f4d5ad..04e34e76e1 100644 --- a/plugin/datacap-plugin-cratedb-http/pom.xml +++ b/plugin/datacap-plugin-cratedb-http/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-cratedb/pom.xml b/plugin/datacap-plugin-cratedb/pom.xml index 894badd3fb..459987da22 100644 --- a/plugin/datacap-plugin-cratedb/pom.xml +++ b/plugin/datacap-plugin-cratedb/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-db2/pom.xml b/plugin/datacap-plugin-db2/pom.xml index b224311f30..ff30bf9ff2 100644 --- a/plugin/datacap-plugin-db2/pom.xml +++ b/plugin/datacap-plugin-db2/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-dm/pom.xml b/plugin/datacap-plugin-dm/pom.xml index c192ce0da7..c86270d709 100644 --- a/plugin/datacap-plugin-dm/pom.xml +++ b/plugin/datacap-plugin-dm/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-doris/pom.xml b/plugin/datacap-plugin-doris/pom.xml index 2e5ed95404..a7dee5a386 100644 --- a/plugin/datacap-plugin-doris/pom.xml +++ b/plugin/datacap-plugin-doris/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-dremio/pom.xml b/plugin/datacap-plugin-dremio/pom.xml index ef7d674424..af1334e579 100644 --- a/plugin/datacap-plugin-dremio/pom.xml +++ b/plugin/datacap-plugin-dremio/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-druid/pom.xml b/plugin/datacap-plugin-druid/pom.xml index 867ca17150..2af8f7dd9e 100644 --- a/plugin/datacap-plugin-druid/pom.xml +++ b/plugin/datacap-plugin-druid/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-duckdb/pom.xml b/plugin/datacap-plugin-duckdb/pom.xml index 914ccba408..9683265dbf 100644 --- a/plugin/datacap-plugin-duckdb/pom.xml +++ b/plugin/datacap-plugin-duckdb/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-elasticsearch-8x/pom.xml b/plugin/datacap-plugin-elasticsearch-8x/pom.xml index 56406395ce..17afd8aaf1 100644 --- a/plugin/datacap-plugin-elasticsearch-8x/pom.xml +++ b/plugin/datacap-plugin-elasticsearch-8x/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-greptimedb/pom.xml b/plugin/datacap-plugin-greptimedb/pom.xml index bdb9093a41..60daf15072 100644 --- a/plugin/datacap-plugin-greptimedb/pom.xml +++ b/plugin/datacap-plugin-greptimedb/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-h2-tcp/pom.xml b/plugin/datacap-plugin-h2-tcp/pom.xml index b45536abad..793ce29360 100644 --- a/plugin/datacap-plugin-h2-tcp/pom.xml +++ b/plugin/datacap-plugin-h2-tcp/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-h2/pom.xml b/plugin/datacap-plugin-h2/pom.xml index 84817dae4e..837c4d8d6c 100644 --- a/plugin/datacap-plugin-h2/pom.xml +++ b/plugin/datacap-plugin-h2/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-hdfs/pom.xml b/plugin/datacap-plugin-hdfs/pom.xml index 0485e80f36..e2416b1803 100644 --- a/plugin/datacap-plugin-hdfs/pom.xml +++ b/plugin/datacap-plugin-hdfs/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-hive-2x/pom.xml b/plugin/datacap-plugin-hive-2x/pom.xml index e4303ece19..6623239af8 100644 --- a/plugin/datacap-plugin-hive-2x/pom.xml +++ b/plugin/datacap-plugin-hive-2x/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-hologres/pom.xml b/plugin/datacap-plugin-hologres/pom.xml index 875cd3e7d8..f108e81099 100644 --- a/plugin/datacap-plugin-hologres/pom.xml +++ b/plugin/datacap-plugin-hologres/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-ignite/pom.xml b/plugin/datacap-plugin-ignite/pom.xml index 74837d24f6..44eca88f43 100644 --- a/plugin/datacap-plugin-ignite/pom.xml +++ b/plugin/datacap-plugin-ignite/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-impala/pom.xml b/plugin/datacap-plugin-impala/pom.xml index 3e61ff1bec..4c542ef1d0 100644 --- a/plugin/datacap-plugin-impala/pom.xml +++ b/plugin/datacap-plugin-impala/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-influxdb/pom.xml b/plugin/datacap-plugin-influxdb/pom.xml index 83ffdec5ba..47e0eb8118 100644 --- a/plugin/datacap-plugin-influxdb/pom.xml +++ b/plugin/datacap-plugin-influxdb/pom.xml @@ -5,7 +5,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-iotdb/pom.xml b/plugin/datacap-plugin-iotdb/pom.xml index 6d9f780e91..b7da932847 100644 --- a/plugin/datacap-plugin-iotdb/pom.xml +++ b/plugin/datacap-plugin-iotdb/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-kafka/pom.xml b/plugin/datacap-plugin-kafka/pom.xml index f77b6398f4..289d398265 100644 --- a/plugin/datacap-plugin-kafka/pom.xml +++ b/plugin/datacap-plugin-kafka/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-kylin/pom.xml b/plugin/datacap-plugin-kylin/pom.xml index 63155cc02d..19c8f6780e 100644 --- a/plugin/datacap-plugin-kylin/pom.xml +++ b/plugin/datacap-plugin-kylin/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-kyuubi/pom.xml b/plugin/datacap-plugin-kyuubi/pom.xml index d6df748ac3..f0922453e2 100644 --- a/plugin/datacap-plugin-kyuubi/pom.xml +++ b/plugin/datacap-plugin-kyuubi/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-matrixone/pom.xml b/plugin/datacap-plugin-matrixone/pom.xml index 6f2d7a6b3c..0b1370e35d 100644 --- a/plugin/datacap-plugin-matrixone/pom.xml +++ b/plugin/datacap-plugin-matrixone/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-monetdb/pom.xml b/plugin/datacap-plugin-monetdb/pom.xml index ec81e9bcc4..3adde43cda 100644 --- a/plugin/datacap-plugin-monetdb/pom.xml +++ b/plugin/datacap-plugin-monetdb/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-mongo-atlas/pom.xml b/plugin/datacap-plugin-mongo-atlas/pom.xml index fb3e120d8a..bad6f60dc0 100644 --- a/plugin/datacap-plugin-mongo-atlas/pom.xml +++ b/plugin/datacap-plugin-mongo-atlas/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-mongo-community/pom.xml b/plugin/datacap-plugin-mongo-community/pom.xml index ad1f685404..32c2c97947 100644 --- a/plugin/datacap-plugin-mongo-community/pom.xml +++ b/plugin/datacap-plugin-mongo-community/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-mysql/pom.xml b/plugin/datacap-plugin-mysql/pom.xml index 4b96130547..14a20a1271 100644 --- a/plugin/datacap-plugin-mysql/pom.xml +++ b/plugin/datacap-plugin-mysql/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-neo4j/pom.xml b/plugin/datacap-plugin-neo4j/pom.xml index 7988bc2721..b6f053c60f 100644 --- a/plugin/datacap-plugin-neo4j/pom.xml +++ b/plugin/datacap-plugin-neo4j/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-oceanbase/pom.xml b/plugin/datacap-plugin-oceanbase/pom.xml index e3caeea5ad..0a319ecb5f 100644 --- a/plugin/datacap-plugin-oceanbase/pom.xml +++ b/plugin/datacap-plugin-oceanbase/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-oracle/pom.xml b/plugin/datacap-plugin-oracle/pom.xml index 1c96f9e1ba..4925881861 100644 --- a/plugin/datacap-plugin-oracle/pom.xml +++ b/plugin/datacap-plugin-oracle/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-paradedb/pom.xml b/plugin/datacap-plugin-paradedb/pom.xml index b0e5b82566..a5d245443c 100644 --- a/plugin/datacap-plugin-paradedb/pom.xml +++ b/plugin/datacap-plugin-paradedb/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-phoenix/pom.xml b/plugin/datacap-plugin-phoenix/pom.xml index 3320f20a5a..8e56a99481 100644 --- a/plugin/datacap-plugin-phoenix/pom.xml +++ b/plugin/datacap-plugin-phoenix/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-pinot/pom.xml b/plugin/datacap-plugin-pinot/pom.xml index c9b60322f6..66636dbb11 100644 --- a/plugin/datacap-plugin-pinot/pom.xml +++ b/plugin/datacap-plugin-pinot/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-postgresql/pom.xml b/plugin/datacap-plugin-postgresql/pom.xml index da791908d6..829a2c46dc 100644 --- a/plugin/datacap-plugin-postgresql/pom.xml +++ b/plugin/datacap-plugin-postgresql/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-presto/pom.xml b/plugin/datacap-plugin-presto/pom.xml index 3246a3ade3..9596a6e37c 100644 --- a/plugin/datacap-plugin-presto/pom.xml +++ b/plugin/datacap-plugin-presto/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-questdb/pom.xml b/plugin/datacap-plugin-questdb/pom.xml index 21295faf62..1753d32aa6 100644 --- a/plugin/datacap-plugin-questdb/pom.xml +++ b/plugin/datacap-plugin-questdb/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-redis-jdbc/pom.xml b/plugin/datacap-plugin-redis-jdbc/pom.xml index 4c19e490c5..a518c4d4e5 100644 --- a/plugin/datacap-plugin-redis-jdbc/pom.xml +++ b/plugin/datacap-plugin-redis-jdbc/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-redis/pom.xml b/plugin/datacap-plugin-redis/pom.xml index 0a005e78cc..3029c9e977 100644 --- a/plugin/datacap-plugin-redis/pom.xml +++ b/plugin/datacap-plugin-redis/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-scylladb/pom.xml b/plugin/datacap-plugin-scylladb/pom.xml index 062b30bbe1..4e06ad9d46 100644 --- a/plugin/datacap-plugin-scylladb/pom.xml +++ b/plugin/datacap-plugin-scylladb/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-snowflake/pom.xml b/plugin/datacap-plugin-snowflake/pom.xml index d8e8cb3ba2..5f4cd44556 100644 --- a/plugin/datacap-plugin-snowflake/pom.xml +++ b/plugin/datacap-plugin-snowflake/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-solr/pom.xml b/plugin/datacap-plugin-solr/pom.xml index 9ca710b685..d6118a2cf7 100644 --- a/plugin/datacap-plugin-solr/pom.xml +++ b/plugin/datacap-plugin-solr/pom.xml @@ -5,7 +5,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-sqlserver/pom.xml b/plugin/datacap-plugin-sqlserver/pom.xml index ad43e1ef5f..5cd77d6998 100644 --- a/plugin/datacap-plugin-sqlserver/pom.xml +++ b/plugin/datacap-plugin-sqlserver/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-starrocks/pom.xml b/plugin/datacap-plugin-starrocks/pom.xml index 35f43d65b8..93eda22bd3 100644 --- a/plugin/datacap-plugin-starrocks/pom.xml +++ b/plugin/datacap-plugin-starrocks/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-tdengine/pom.xml b/plugin/datacap-plugin-tdengine/pom.xml index 812ac565a9..024246c3b9 100644 --- a/plugin/datacap-plugin-tdengine/pom.xml +++ b/plugin/datacap-plugin-tdengine/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-timescale/pom.xml b/plugin/datacap-plugin-timescale/pom.xml index 33cc351453..33caafd808 100644 --- a/plugin/datacap-plugin-timescale/pom.xml +++ b/plugin/datacap-plugin-timescale/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-trino/pom.xml b/plugin/datacap-plugin-trino/pom.xml index e1f8b7a744..80356eaa48 100644 --- a/plugin/datacap-plugin-trino/pom.xml +++ b/plugin/datacap-plugin-trino/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/plugin/datacap-plugin-ydb/pom.xml b/plugin/datacap-plugin-ydb/pom.xml index 71df5896dc..46b94b4f98 100644 --- a/plugin/datacap-plugin-ydb/pom.xml +++ b/plugin/datacap-plugin-ydb/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/plugin/datacap-plugin-zookeeper/pom.xml b/plugin/datacap-plugin-zookeeper/pom.xml index 08a9d8f6f5..f5b4f5099e 100644 --- a/plugin/datacap-plugin-zookeeper/pom.xml +++ b/plugin/datacap-plugin-zookeeper/pom.xml @@ -5,7 +5,7 @@ datacap io.edurt.datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 7f3ae56bfb..d1cf565296 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap pom - 2024.4.0 + 2024.4.1-SNAPSHOT client/datacap-cli diff --git a/scheduler/datacap-scheduler-local/pom.xml b/scheduler/datacap-scheduler-local/pom.xml index dd5979c4eb..dc321d6682 100644 --- a/scheduler/datacap-scheduler-local/pom.xml +++ b/scheduler/datacap-scheduler-local/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/scheduler/datacap-scheduler-spi/pom.xml b/scheduler/datacap-scheduler-spi/pom.xml index a29e0d9262..f1e0505808 100644 --- a/scheduler/datacap-scheduler-spi/pom.xml +++ b/scheduler/datacap-scheduler-spi/pom.xml @@ -4,7 +4,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/shaded/datacap-shaded-neo4j/pom.xml b/shaded/datacap-shaded-neo4j/pom.xml index 42fb03da02..3a4670eebf 100644 --- a/shaded/datacap-shaded-neo4j/pom.xml +++ b/shaded/datacap-shaded-neo4j/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/shaded/datacap-shaded-pinot/pom.xml b/shaded/datacap-shaded-pinot/pom.xml index 4b231ef191..673d3598e5 100644 --- a/shaded/datacap-shaded-pinot/pom.xml +++ b/shaded/datacap-shaded-pinot/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/shaded/datacap-shaded-ydb/pom.xml b/shaded/datacap-shaded-ydb/pom.xml index 6cae683705..0dfa67be97 100644 --- a/shaded/datacap-shaded-ydb/pom.xml +++ b/shaded/datacap-shaded-ydb/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/test/datacap-test-convert/pom.xml b/test/datacap-test-convert/pom.xml index 8d451c0846..ae9c96d065 100644 --- a/test/datacap-test-convert/pom.xml +++ b/test/datacap-test-convert/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/test/datacap-test-core/pom.xml b/test/datacap-test-core/pom.xml index 52a5b273df..2e82cdb5e7 100644 --- a/test/datacap-test-core/pom.xml +++ b/test/datacap-test-core/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/test/datacap-test-executor/pom.xml b/test/datacap-test-executor/pom.xml index 80c1586d7c..54bafd4131 100644 --- a/test/datacap-test-executor/pom.xml +++ b/test/datacap-test-executor/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/test/datacap-test-fs/pom.xml b/test/datacap-test-fs/pom.xml index 43e5c643bd..d7862dd0f5 100644 --- a/test/datacap-test-fs/pom.xml +++ b/test/datacap-test-fs/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/test/datacap-test-lib/pom.xml b/test/datacap-test-lib/pom.xml index 104679b1dc..a443fb9171 100644 --- a/test/datacap-test-lib/pom.xml +++ b/test/datacap-test-lib/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/test/datacap-test-plugin/pom.xml b/test/datacap-test-plugin/pom.xml index 7777b48de1..b8e9b63d0a 100644 --- a/test/datacap-test-plugin/pom.xml +++ b/test/datacap-test-plugin/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml diff --git a/test/datacap-test-scheduler/pom.xml b/test/datacap-test-scheduler/pom.xml index b921adbc9a..89a87bbfe4 100644 --- a/test/datacap-test-scheduler/pom.xml +++ b/test/datacap-test-scheduler/pom.xml @@ -6,7 +6,7 @@ io.edurt.datacap datacap - 2024.4.0 + 2024.4.1-SNAPSHOT ../../pom.xml From e18d09eca8553f5059f133c0a2ca8aa2324f674b Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Mon, 2 Dec 2024 18:56:01 +0800 Subject: [PATCH 02/17] feat(core): optimize and release new version script --- configure/metadata.json | 268 ++++++++++++------------ configure/publish/publish-newVersion.sh | 10 +- 2 files changed, 143 insertions(+), 135 deletions(-) diff --git a/configure/metadata.json b/configure/metadata.json index 231002d400..106d382a30 100644 --- a/configure/metadata.json +++ b/configure/metadata.json @@ -13,12 +13,12 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/mysql.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "8.0", "5.7" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-mysql/2024.4.0/datacap-plugin-mysql-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-mysql/2024.4.1-SNAPSHOT/datacap-plugin-mysql-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-clickhouse", @@ -29,11 +29,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/clickhouse.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-clickhouse/2024.4.0/datacap-plugin-clickhouse-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-clickhouse/2024.4.1-SNAPSHOT/datacap-plugin-clickhouse-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-influxdb", @@ -44,11 +44,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/influxdb.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-influxdb/2024.4.0/datacap-plugin-influxdb-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-influxdb/2024.4.1-SNAPSHOT/datacap-plugin-influxdb-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-solr", @@ -59,11 +59,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/solr.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-solr/2024.4.0/datacap-plugin-solr-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-solr/2024.4.1-SNAPSHOT/datacap-plugin-solr-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-cratedb", @@ -74,11 +74,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/cratedb.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-cratedb/2024.4.0/datacap-plugin-cratedb-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-cratedb/2024.4.1-SNAPSHOT/datacap-plugin-cratedb-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-cratedb-http", @@ -89,11 +89,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/cratedbhttp.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-cratedb-http/2024.4.0/datacap-plugin-cratedbhttp-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-cratedb-http/2024.4.1-SNAPSHOT/datacap-plugin-cratedb-http-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-zookeeper", @@ -104,11 +104,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/zookeeper.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-zookeeper/2024.4.0/datacap-plugin-zookeeper-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-zookeeper/2024.4.1-SNAPSHOT/datacap-plugin-zookeeper-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-kafka", @@ -119,11 +119,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/kafka.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-kafka/2024.4.0/datacap-plugin-kafka-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-kafka/2024.4.1-SNAPSHOT/datacap-plugin-kafka-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-redis", @@ -134,11 +134,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/redis.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-redis/2024.4.0/datacap-plugin-redis-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-redis/2024.4.1-SNAPSHOT/datacap-plugin-redis-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-h2", @@ -149,11 +149,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/h2.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-h2/2024.4.0/datacap-plugin-h2-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-h2/2024.4.1-SNAPSHOT/datacap-plugin-h2-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-db2", @@ -164,11 +164,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/db2.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-db2/2024.4.0/datacap-plugin-db2-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-db2/2024.4.1-SNAPSHOT/datacap-plugin-db2-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-dm", @@ -179,11 +179,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/dm.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-dm/2024.4.0/datacap-plugin-dm-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-dm/2024.4.1-SNAPSHOT/datacap-plugin-dm-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-hdfs", @@ -194,11 +194,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/hdfs.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-hdfs/2024.4.0/datacap-plugin-hdfs-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-hdfs/2024.4.1-SNAPSHOT/datacap-plugin-hdfs-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-alioss", @@ -209,11 +209,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/alioss.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-alioss/2024.4.0/datacap-plugin-alioss-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-alioss/2024.4.1-SNAPSHOT/datacap-plugin-alioss-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-dremio", @@ -224,11 +224,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/dremio.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-dremio/2024.4.0/datacap-plugin-dremio-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-dremio/2024.4.1-SNAPSHOT/datacap-plugin-dremio-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-druid", @@ -239,11 +239,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/druid.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-druid/2024.4.0/datacap-plugin-druid-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-druid/2024.4.1-SNAPSHOT/datacap-plugin-druid-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-duckdb", @@ -254,11 +254,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/duckdb.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-duckdb/2024.4.0/datacap-plugin-duckdb-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-duckdb/2024.4.1-SNAPSHOT/datacap-plugin-duckdb-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-pinot", @@ -269,11 +269,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/pinot.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-pinot/2024.4.0/datacap-plugin-pinot-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-pinot/2024.4.1-SNAPSHOT/datacap-plugin-pinot-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-cassandra", @@ -284,11 +284,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/cassandra.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-cassandra/2024.4.0/datacap-plugin-cassandra-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-cassandra/2024.4.1-SNAPSHOT/datacap-plugin-cassandra-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-matrixone", @@ -299,11 +299,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/matrixone.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-matrixone/2024.4.0/datacap-plugin-matrixone-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-matrixone/2024.4.1-SNAPSHOT/datacap-plugin-matrixone-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-scylladb", @@ -314,11 +314,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/scylladb.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-scylladb/2024.4.0/datacap-plugin-scylladb-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-scylladb/2024.4.1-SNAPSHOT/datacap-plugin-scylladb-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-paradedb", @@ -329,11 +329,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/paradedb.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-paradedb/2024.4.0/datacap-plugin-paradedb-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-paradedb/2024.4.1-SNAPSHOT/datacap-plugin-paradedb-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-hive-2x", @@ -344,11 +344,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/hive2x.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "2.x" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-hive-2x/2024.4.0/datacap-plugin-hive-2x-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-hive-2x/2024.4.1-SNAPSHOT/datacap-plugin-hive-2x-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-kyuubi", @@ -359,11 +359,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/kyuubi.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-kyuubi/2024.4.0/datacap-plugin-kyuubi-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-kyuubi/2024.4.1-SNAPSHOT/datacap-plugin-kyuubi-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-ignite", @@ -374,11 +374,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/ignite.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-ignite/2024.4.0/datacap-plugin-ignite-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-ignite/2024.4.1-SNAPSHOT/datacap-plugin-ignite-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-impala", @@ -389,11 +389,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/impala.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-impala/2024.4.0/datacap-plugin-impala-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-impala/2024.4.1-SNAPSHOT/datacap-plugin-impala-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-kylin", @@ -404,11 +404,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/kylin.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-kylin/2024.4.0/datacap-plugin-kylin-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-kylin/2024.4.1-SNAPSHOT/datacap-plugin-kylin-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-timescale", @@ -419,11 +419,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/timescale.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-timescale/2024.4.0/datacap-plugin-timescale-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-timescale/2024.4.1-SNAPSHOT/datacap-plugin-timescale-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-iotdb", @@ -434,11 +434,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/iotdb.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-iotdb/2024.4.0/datacap-plugin-iotdb-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-iotdb/2024.4.1-SNAPSHOT/datacap-plugin-iotdb-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-monetdb", @@ -449,11 +449,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/monetdb.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-monetdb/2024.4.0/datacap-plugin-monetdb-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-monetdb/2024.4.1-SNAPSHOT/datacap-plugin-monetdb-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-ydb", @@ -464,11 +464,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/ydb.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-ydb/2024.4.0/datacap-plugin-ydb-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-ydb/2024.4.1-SNAPSHOT/datacap-plugin-ydb-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-neo4j", @@ -479,11 +479,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/neo4j.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-neo4j/2024.4.0/datacap-plugin-neo4j-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-neo4j/2024.4.1-SNAPSHOT/datacap-plugin-neo4j-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-oceanbase", @@ -494,11 +494,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/oceanbase.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-oceanbase/2024.4.0/datacap-plugin-oceanbase-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-oceanbase/2024.4.1-SNAPSHOT/datacap-plugin-oceanbase-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-oracle", @@ -509,11 +509,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/oracle.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-oracle/2024.4.0/datacap-plugin-oracle-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-oracle/2024.4.1-SNAPSHOT/datacap-plugin-oracle-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-phoenix", @@ -524,11 +524,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/phoenix.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-phoenix/2024.4.0/datacap-plugin-phoenix-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-phoenix/2024.4.1-SNAPSHOT/datacap-plugin-phoenix-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-postgresql", @@ -539,11 +539,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/postgresql.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-postgresql/2024.4.0/datacap-plugin-postgresql-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-postgresql/2024.4.1-SNAPSHOT/datacap-plugin-postgresql-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-presto", @@ -554,11 +554,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/presto.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-presto/2024.4.0/datacap-plugin-presto-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-presto/2024.4.1-SNAPSHOT/datacap-plugin-presto-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-snowflake", @@ -569,11 +569,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/snowflake.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-snowflake/2024.4.0/datacap-plugin-snowflake-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-snowflake/2024.4.1-SNAPSHOT/datacap-plugin-snowflake-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-sqlserver", @@ -584,11 +584,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/sqlserver.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-sqlserver/2024.4.0/datacap-plugin-sqlserver-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-sqlserver/2024.4.1-SNAPSHOT/datacap-plugin-sqlserver-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-tdengine", @@ -599,11 +599,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/tdengine.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-tdengine/2024.4.0/datacap-plugin-tdengine-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-tdengine/2024.4.1-SNAPSHOT/datacap-plugin-tdengine-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-trino", @@ -614,11 +614,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/trino.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-trino/2024.4.0/datacap-plugin-trino-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-trino/2024.4.1-SNAPSHOT/datacap-plugin-trino-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-doris", @@ -629,11 +629,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/doris.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-doris/2024.4.0/datacap-plugin-doris-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-doris/2024.4.1-SNAPSHOT/datacap-plugin-doris-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-starrocks", @@ -644,11 +644,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/starrocks.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-starrocks/2024.4.0/datacap-plugin-starrocks-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-starrocks/2024.4.1-SNAPSHOT/datacap-plugin-starrocks-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-hologres", @@ -659,11 +659,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/hologres.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-hologres/2024.4.0/datacap-plugin-hologres-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-hologres/2024.4.1-SNAPSHOT/datacap-plugin-hologres-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-greptimedb", @@ -674,11 +674,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/greptimedb.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-greptimedb/2024.4.0/datacap-plugin-greptimedb-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-greptimedb/2024.4.1-SNAPSHOT/datacap-plugin-greptimedb-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-questdb", @@ -689,11 +689,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/questdb.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-questdb/2024.4.0/datacap-plugin-questdb-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-questdb/2024.4.1-SNAPSHOT/datacap-plugin-questdb-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-h2-tcp", @@ -704,11 +704,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/h2tcp.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-h2-tcp/2024.4.0/datacap-plugin-h2-tcp-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-h2-tcp/2024.4.1-SNAPSHOT/datacap-plugin-h2-tcp-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-clickhouse-http", @@ -719,11 +719,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/clickhousehttp.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-clickhouse-http/2024.4.0/datacap-plugin-clickhouse-http-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-clickhouse-http/2024.4.1-SNAPSHOT/datacap-plugin-clickhouse-http-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-ceresdb", @@ -734,11 +734,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/ceresdb.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-ceresdb/2024.4.0/datacap-plugin-ceresdb-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-ceresdb/2024.4.1-SNAPSHOT/datacap-plugin-ceresdb-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-redis-jdbc", @@ -749,11 +749,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/redisjdbc.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-redis-jdbc/2024.4.0/datacap-plugin-redis-jdbc-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-redis-jdbc/2024.4.1-SNAPSHOT/datacap-plugin-redis-jdbc-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-elasticsearch-8x", @@ -764,11 +764,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/elasticsearch8x.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "8.x" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-elasticsearch-8x/2024.4.0/datacap-plugin-elasticsearch-8x-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-elasticsearch-8x/2024.4.1-SNAPSHOT/datacap-plugin-elasticsearch-8x-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-mongo-atlas", @@ -779,11 +779,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/mongoatlas.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-mongo-atlas/2024.4.0/datacap-plugin-mongo-atlas-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-mongo-atlas/2024.4.1-SNAPSHOT/datacap-plugin-mongo-atlas-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-plugin-mongo-community", @@ -794,11 +794,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/plugin/mongocommunity.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-mongo-community/2024.4.0/datacap-plugin-mongo-community-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-plugin-mongo-community/2024.4.1-SNAPSHOT/datacap-plugin-mongo-community-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-convert-csv", @@ -809,11 +809,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/convert/csv.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-convert-csv/2024.4.0/convert/datacap-convert-csv-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-convert-csv/2024.4.1-SNAPSHOT/datacap-convert-csv-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-convert-txt", @@ -824,11 +824,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/convert/txt.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-convert-txt/2024.4.0/convert/datacap-convert-txt-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-convert-txt/2024.4.1-SNAPSHOT/datacap-convert-txt-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-convert-json", @@ -839,11 +839,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/convert/json.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-convert-json/2024.4.0/convert/datacap-convert-json-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-convert-json/2024.4.1-SNAPSHOT/datacap-convert-json-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-convert-xml", @@ -854,11 +854,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/convert/xml.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-convert-xml/2024.4.0/convert/datacap-convert-xml-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-convert-xml/2024.4.1-SNAPSHOT/datacap-convert-xml-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-convert-none", @@ -869,11 +869,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/convert/none.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-convert-none/2024.4.0/convert/datacap-convert-none-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-convert-none/2024.4.1-SNAPSHOT/datacap-convert-none-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-executor-local", @@ -884,11 +884,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/executor/local.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-executor-local/2024.4.0/executor/datacap-executor-local-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-executor-local/2024.4.1-SNAPSHOT/datacap-executor-local-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-executor-seatunnel", @@ -899,11 +899,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/executor/seatunnel.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-executor-seatunnel/2024.4.0/executor/datacap-executor-seatunnel-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-executor-seatunnel/2024.4.1-SNAPSHOT/datacap-executor-seatunnel-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-scheduler-local", @@ -914,11 +914,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/scheduler/local.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-scheduler-local/2024.4.0/scheduler/datacap-scheduler-local-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-scheduler-local/2024.4.1-SNAPSHOT/datacap-scheduler-local-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-fs-local", @@ -929,11 +929,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/fs/local.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-fs-local/2024.4.0/fs/datacap-fs-local-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-fs-local/2024.4.1-SNAPSHOT/datacap-fs-local-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-fs-qiniu", @@ -944,11 +944,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/fs/qiniu.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-fs-qiniu/2024.4.0/fs/datacap-fs-qiniu-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-fs-qiniu/2024.4.1-SNAPSHOT/datacap-fs-qiniu-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-fs-alioss", @@ -959,11 +959,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/fs/alioss.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-fs-alioss/2024.4.0/fs/datacap-fs-alioss-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-fs-alioss/2024.4.1-SNAPSHOT/datacap-fs-alioss-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-fs-tencent-cos", @@ -974,11 +974,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/fs/tencent-cos.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-fs-tencent-cos/2024.4.0/fs/datacap-fs-tencent-cos-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-fs-tencent-cos/2024.4.1-SNAPSHOT/datacap-fs-tencent-cos-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-fs-amazon-s3", @@ -989,11 +989,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/fs/amazon-s3.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-fs-amazon-s3/2024.4.0/fs/datacap-fs-amazon-s3-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-fs-amazon-s3/2024.4.1-SNAPSHOT/datacap-fs-amazon-s3-2024.4.1-SNAPSHOT-bin.tar.gz" }, { "key": "datacap-fs-minio", @@ -1004,11 +1004,11 @@ "version": "2024.4.1-SNAPSHOT", "author": "datacap-community", "logo": "http://devlive-cdn.oss-cn-beijing.aliyuncs.com/applications/datacap/resources/logo/fs/minio.svg", - "released": "2024-12-02 18:29:41", + "released": "2024-12-02 18:54:48", "supportVersion": [ "ALL" ], - "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-fs-minio/2024.4.0/fs/datacap-fs-minio-bin.tar.gz" + "url": "https://repo1.maven.org/maven2/io/edurt/datacap/datacap-fs-minio/2024.4.1-SNAPSHOT/datacap-fs-minio-2024.4.1-SNAPSHOT-bin.tar.gz" } ] } \ No newline at end of file diff --git a/configure/publish/publish-newVersion.sh b/configure/publish/publish-newVersion.sh index f4ac95fdda..82fa81afc7 100644 --- a/configure/publish/publish-newVersion.sh +++ b/configure/publish/publish-newVersion.sh @@ -42,8 +42,16 @@ job_runner_apply() { echo "Apply new version for metadata ..." # Update version and URL in metadata.json using perl + # 更新 version 字段 perl -i -pe 's/"version": "[^"]*"/"version": "'"$VERSION"'"/' "$HOME/configure/metadata.json" - perl -i -pe 's|/plugins/[^/]+/|/plugins/'"$VERSION"'/|g' "$HOME/configure/metadata.json" + + # 更新 url 字段中的版本号 (针对类似 2024.4.0 这样的版本格式) + # Update the version number in the url field (for a version format like 2024.4.0) + perl -i -pe 's/\/\d{4}\.\d+\.\d+\//\/'"$VERSION"'\//' "$HOME/configure/metadata.json" + perl -i -pe 's/-\d{4}\.\d+\.\d+-bin/-'"$VERSION"'-bin/' "$HOME/configure/metadata.json" + + # 更新发布日期 + # Update publish date perl -i -pe 's/"released": "[^"]*"/"released": "'"$CURRENT_DATE"'"/' "$HOME/configure/metadata.json" printf "Apply new version for web ...\n" From 27ad890477138d317723fc05258f0a1bb85283e3 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Tue, 3 Dec 2024 17:06:14 +0800 Subject: [PATCH 03/17] feat(parser): building a perfect SQL parser --- .gitignore | 4 + .../io/edurt/datacap/sql/parser/SqlBase.g4 | 592 ++++++- .../src/main/java/SqlBase.tokens | 20 - .../src/main/java/SqlBaseLexer.tokens | 20 - .../edurt/datacap/sql/SQLParseException.java | 15 + .../java/io/edurt/datacap/sql/SQLParser.java | 39 + ...tener.java => SQLParserErrorListener.java} | 9 +- .../java/io/edurt/datacap/sql/SQLVisitor.java | 398 +++++ .../java/io/edurt/datacap/sql/SqlBase.java | 25 - .../edurt/datacap/sql/SqlBaseFormatter.java | 61 - .../io/edurt/datacap/sql/SqlBaseToken.java | 11 - .../io/edurt/datacap/sql/SqlBaseVisitor.java | 136 -- .../datacap/sql/SqlCaseInsensitiveStream.java | 78 - .../io/edurt/datacap/sql/node/Expression.java | 20 + .../datacap/sql/node/clause/JoinClause.java | 20 + .../datacap/sql/node/clause/LimitClause.java | 12 + .../sql/node/element/OrderByElement.java | 13 + .../sql/node/element/SelectElement.java | 14 + .../sql/node/element/TableElement.java | 18 + .../edurt/datacap/sql/parser/SqlBase.interp | 55 - .../sql/parser/SqlBaseBaseListener.java | 184 --- .../sql/parser/SqlBaseBaseVisitor.java | 99 -- .../datacap/sql/parser/SqlBaseLexer.interp | 67 - .../datacap/sql/parser/SqlBaseLexer.java | 243 --- .../datacap/sql/parser/SqlBaseListener.java | 130 -- .../datacap/sql/parser/SqlBaseParser.java | 911 ----------- .../datacap/sql/parser/SqlBaseVisitor.java | 85 - .../datacap/sql/statement/SQLStatement.java | 21 + .../sql/statement/SelectStatement.java | 30 + .../io/edurt/datacap/sql/KafkaParserTest.java | 43 - .../io/edurt/datacap/sql/ShowPathsTest.java | 26 - .../datacap/sql/SqlBaseFormatterTest.java | 15 - .../service/security/UserDetailsService.java | 1 + docs/docs/release/latest.en.md | 15 +- docs/docs/release/latest.md | 15 +- driver/datacap-driver-mongodb/pom.xml | 27 + .../edurt/datacap/driver/MongoConnection.java | 474 ++++++ .../edurt/datacap/driver/MongoJdbcDriver.java | 93 ++ .../datacap/driver/MongoQueryParser.java | 235 +++ .../edurt/datacap/driver/MongoResultSet.java | 1424 +++++++++++++++++ .../edurt/datacap/driver/MongoStatement.java | 352 ++++ pom.xml | 9 + test/datacap-test-driver/pom.xml | 23 + .../test/mongo/MongoJdbcDriverTest.java | 41 + .../test/mongo/MongoQueryParserTest.java | 34 + test/datacap-test-parser/pom.xml | 23 + .../test/basic/SelectStatementTest.java | 153 ++ 47 files changed, 4072 insertions(+), 2261 deletions(-) delete mode 100644 core/datacap-parser/src/main/java/SqlBase.tokens delete mode 100644 core/datacap-parser/src/main/java/SqlBaseLexer.tokens create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLParseException.java create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLParser.java rename core/datacap-parser/src/main/java/io/edurt/datacap/sql/{UnderLineListener.java => SQLParserErrorListener.java} (63%) create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java delete mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBase.java delete mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBaseFormatter.java delete mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBaseToken.java delete mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBaseVisitor.java delete mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlCaseInsensitiveStream.java create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/Expression.java create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/clause/JoinClause.java create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/clause/LimitClause.java create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/element/OrderByElement.java create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/element/SelectElement.java create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/element/TableElement.java delete mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBase.interp delete mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseBaseListener.java delete mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseBaseVisitor.java delete mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseLexer.interp delete mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseLexer.java delete mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseListener.java delete mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseParser.java delete mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseVisitor.java create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/SQLStatement.java create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/SelectStatement.java delete mode 100644 core/datacap-parser/src/test/java/io/edurt/datacap/sql/KafkaParserTest.java delete mode 100644 core/datacap-parser/src/test/java/io/edurt/datacap/sql/ShowPathsTest.java delete mode 100644 core/datacap-parser/src/test/java/io/edurt/datacap/sql/SqlBaseFormatterTest.java create mode 100644 driver/datacap-driver-mongodb/pom.xml create mode 100644 driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoConnection.java create mode 100644 driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoJdbcDriver.java create mode 100644 driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoQueryParser.java create mode 100644 driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoResultSet.java create mode 100644 driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoStatement.java create mode 100644 test/datacap-test-driver/pom.xml create mode 100644 test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java create mode 100644 test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoQueryParserTest.java create mode 100644 test/datacap-test-parser/pom.xml create mode 100644 test/datacap-test-parser/src/test/java/io/edurt/datacap/test/basic/SelectStatementTest.java diff --git a/.gitignore b/.gitignore index bc41b9c43f..32849a44ac 100644 --- a/.gitignore +++ b/.gitignore @@ -62,6 +62,10 @@ depcheck-output.json parser/datacap-parser-mysql/src/main/java parser/datacap-parser-trino/src/main/java/*.tokens parser/datacap-parser-trino/src/main/java/io/edurt/datacap/parser/antlr +core/datacap-parser/src/main/java/*.tokens +core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/*.java +core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/*.interp +!core/datacap-parser/src/main/java/io/edurt/datacap/sql/node # Skip convert # convert/datacap-convert-txt/*.txt diff --git a/core/datacap-parser/src/main/antlr4/io/edurt/datacap/sql/parser/SqlBase.g4 b/core/datacap-parser/src/main/antlr4/io/edurt/datacap/sql/parser/SqlBase.g4 index 0fdec7ccb1..ca8c6a19d0 100644 --- a/core/datacap-parser/src/main/antlr4/io/edurt/datacap/sql/parser/SqlBase.g4 +++ b/core/datacap-parser/src/main/antlr4/io/edurt/datacap/sql/parser/SqlBase.g4 @@ -1,68 +1,580 @@ grammar SqlBase; -singleStatement:(statement)*; - -SHOW: [Ss][Hh][Oo][Ww]; -PATHS: [Pp][Aa][Tt][Hh][Ss]; -TOPICS: 'TOPICS'; -CONSUMERS: 'CONSUMERS'; -DATABASES: [Dd][Aa][Tt][Aa][Bb][Aa][Ss][Es][Ss]; -TABLES: [Tt][Aa][Bb][Ll][Ee][Ss]; +singleStatement: (statement)* EOF; + +// Keywords SELECT: [Ss][Ee][Ll][Ee][Cc][Tt]; FROM: [Ff][Rr][Oo][Mm]; +WHERE: [Ww][Hh][Ee][Rr][Ee]; +ORDER: [Oo][Rr][Dd][Ee][Rr]; +BY: [Bb][Yy]; +GROUP: [Gg][Rr][Oo][Uu][Pp]; +HAVING: [Hh][Aa][Vv][Ii][Nn][Gg]; +LIMIT: [Ll][Ii][Mm][Ii][Tt]; +OFFSET: [Oo][Ff][Ff][Ss][Ee][Tt]; +ASC: [Aa][Ss][Cc]; +DESC: [Dd][Ee][Ss][Cc]; +AS: [Aa][Ss]; +ON: [Oo][Nn]; +USING: [Uu][Ss][Ii][Nn][Gg]; +INNER: [Ii][Nn][Nn][Ee][Rr]; +LEFT: [Ll][Ee][Ff][Tt]; +RIGHT: [Rr][Ii][Gg][Hh][Tt]; +FULL: [Ff][Uu][Ll][Ll]; +OUTER: [Oo][Uu][Tt][Ee][Rr]; +JOIN: [Jj][Oo][Ii][Nn]; +CROSS: [Cc][Rr][Oo][Ss][Ss]; +NATURAL: [Nn][Aa][Tt][Uu][Rr][Aa][Ll]; +INSERT: [Ii][Nn][Ss][Ee][Rr][Tt]; +INTO: [Ii][Nn][Tt][Oo]; +VALUES: [Vv][Aa][Ll][Uu][Ee][Ss]; +UPDATE: [Uu][Pp][Dd][Aa][Tt][Ee]; +SET: [Ss][Ee][Tt]; +DELETE: [Dd][Ee][Ll][Ee][Tt][Ee]; +CREATE: [Cc][Rr][Ee][Aa][Tt][Ee]; +ALTER: [Aa][Ll][Tt][Ee][Rr]; +DROP: [Dd][Rr][Oo][Pp]; +TABLE: [Tt][Aa][Bb][Ll][Ee]; +VIEW: [Vv][Ii][Ee][Ww]; +INDEX: [Ii][Nn][Dd][Ee][Xx]; +PRIMARY: [Pp][Rr][Ii][Mm][Aa][Rr][Yy]; +KEY: [Kk][Ee][Yy]; +FOREIGN: [Ff][Oo][Rr][Ee][Ii][Gg][Nn]; +REFERENCES: [Rr][Ee][Ff][Ee][Rr][Ee][Nn][Cc][Ee][Ss]; +CONSTRAINT: [Cc][Oo][Nn][Ss][Tt][Rr][Aa][Ii][Nn][Tt]; +DEFAULT: [Dd][Ee][Ff][Aa][Uu][Ll][Tt]; +UNIQUE: [Uu][Nn][Ii][Qq][Uu][Ee]; +CHECK: [Cc][Hh][Ee][Cc][Kk]; +COLUMN: [Cc][Oo][Ll][Uu][Mm][Nn]; +DATABASE: [Dd][Aa][Tt][Aa][Bb][Aa][Ss][Ee]; +USE: [Uu][Ss][Ee]; +IF: [Ii][Ff]; +EXISTS: [Ee][Xx][Ii][Ss][Tt][Ss]; +REPLACE: [Rr][Ee][Pp][Ll][Aa][Cc][Ee]; +TEMP: [Tt][Ee][Mm][Pp]; +TEMPORARY: [Tt][Ee][Mm][Pp][Oo][Rr][Aa][Rr][Yy]; + +// Operators +AND: [Aa][Nn][Dd]; +OR: [Oo][Rr]; +NOT: [Nn][Oo][Tt]; +IS: [Ii][Ss]; +NULL: [Nn][Uu][Ll][Ll]; +LIKE: [Ll][Ii][Kk][Ee]; +IN: [Ii][Nn]; +BETWEEN: [Bb][Ee][Tt][Ww][Ee][Ee][Nn]; +CASE: [Cc][Aa][Ss][Ee]; +WHEN: [Ww][Hh][Ee][Nn]; +THEN: [Tt][Hh][Ee][Nn]; +ELSE: [Ee][Ll][Ss][Ee]; +END: [Ee][Nn][Dd]; + +// Others +CHARSET: [Cc][Hh][Aa][Rr][Ss][Ee][Tt]; +COLLATE: [Cc][Oo][Ll][Ll][Aa][Tt][Ee]; +AUTO_INCREMENT: [Aa][Uu][Tt][Oo]'_'[Ii][Nn][Cc][Rr][Ee][Mm][Ee][Nn][Tt]; +COMMENT: [Cc][Oo][Mm][Mm][Ee][Nn][Tt]; +ADD: [Aa][Dd][Dd]; +MODIFY: [Mm][Oo][Dd][Ii][Ff][Yy]; +ENGINE: [Ee][Nn][Gg][Ii][Nn][Ee]; + +tableOptions + : tableOption+ + ; + +tableOption + : ENGINE '=' STRING + | CHARSET '=' STRING + | COLLATE '=' STRING + | AUTO_INCREMENT '=' INTEGER_VALUE + | COMMENT '=' STRING + ; statement - : SHOW childPathStatement - | SELECT columnStatement fromClause - | kafkaStatement + : selectStatement + | insertStatement + | updateStatement + | deleteStatement + | createStatement + | alterStatement + | dropStatement + | useStatement + ; + +// USE statement +useStatement + : USE databaseName + ; + +// SELECT statement +selectStatement + : queryExpression + orderByClause? + limitClause? + ; + +queryExpression + : queryTerm + | queryExpression UNION (ALL)? queryTerm + | queryExpression EXCEPT queryTerm + | queryExpression INTERSECT queryTerm + ; + +queryTerm + : queryPrimary + ; + +queryPrimary + : querySpecification + | '(' queryExpression ')' + ; + +querySpecification + : SELECT (ALL | DISTINCT)? selectElements + fromClause? + whereClause? + groupByClause? + havingClause? + ; + +selectElements + : selectElement (',' selectElement)* + ; + +selectElement + : (tableName '.')? (columnName | '*') (AS? alias)? + | expression (AS? alias)? + | caseExpression (AS? alias)? + ; + +caseExpression + : CASE + (WHEN expression THEN expression)+ + (ELSE expression)? + END + ; + +whereClause + : WHERE expression ; -// -------------------- Kafka Statement -------------------- -kafkaQueryTopicStatement - : SHOW TOPICS - | SHOW DATABASES +groupByClause + : GROUP BY groupByElement (',' groupByElement)* ; -kafkaQueryConsumerStatement - : SHOW CONSUMERS - | SHOW CONSUMERS fromClause - | SHOW TABLES - | SHOW TABLES fromClause + +groupByElement + : expression ; -kafkaQueryStatement - : kafkaQueryTopicStatement - | kafkaQueryConsumerStatement + +havingClause + : HAVING expression ; -kafkaStatement - : kafkaQueryStatement + +orderByClause + : ORDER BY orderByElement (',' orderByElement)* ; -// SHOW PATHS, SHOW PATHS FROM ... -childPathStatement: PATHS | PATHS fromClause; +orderByElement + : expression (ASC | DESC)? + ; -columnStatement: identifier; +limitClause + : LIMIT INTEGER_VALUE (OFFSET INTEGER_VALUE)? + | LIMIT INTEGER_VALUE ',' INTEGER_VALUE + ; -fromClause : FROM tableName; +// INSERT statement +insertStatement + : INSERT (OR REPLACE)? INTO tableName + ('(' columnName (',' columnName)* ')')? + (VALUES insertValuesConstructor (',' insertValuesConstructor)* + | selectStatement) + ; + +insertValuesConstructor + : '(' value (',' value)* ')' + ; -tableName: identifier ('.' identifier)*; -identifier: (IDENTIFIER | STRING | quotedIdentifier)*; -quotedIdentifier: BACKQUOTED_IDENTIFIER; +// UPDATE statement +updateStatement + : UPDATE tableName + SET updateElement (',' updateElement)* + whereClause? + ; + +updateElement + : columnName '=' expression + ; + +// DELETE statement +deleteStatement + : DELETE FROM tableName + whereClause? + ; + +// CREATE statement +createStatement + : createTableStatement + | createViewStatement + | createIndexStatement + | createDatabaseStatement + ; + +createDatabaseStatement + : CREATE DATABASE (IF NOT EXISTS)? databaseName + ; + +createTableStatement + : CREATE (TEMP | TEMPORARY)? TABLE (IF NOT EXISTS)? tableName + '(' tableElement (',' tableElement)* ')' + tableOptions? + ; + +createViewStatement + : CREATE (OR REPLACE)? VIEW tableName + ('(' columnName (',' columnName)* ')')? + AS selectStatement + ; + +createIndexStatement + : CREATE (UNIQUE)? INDEX indexName + ON tableName '(' indexColumn (',' indexColumn)* ')' + ; + +indexColumn + : columnName (ASC | DESC)? + ; + +tableElement + : columnDefinition + | tableConstraint + ; + +columnDefinition + : columnName dataType columnConstraint* + ; + +columnConstraint + : NOT? NULL + | PRIMARY KEY + | UNIQUE + | DEFAULT defaultValue + | (CONSTRAINT constraintName)? foreignKeyClause + | (CONSTRAINT constraintName)? checkConstraint + ; + +tableConstraint + : (CONSTRAINT constraintName)? + ( primaryKeyConstraint + | uniqueConstraint + | foreignKeyConstraint + | checkConstraint + ) + ; + +primaryKeyConstraint + : PRIMARY KEY '(' columnName (',' columnName)* ')' + ; + +uniqueConstraint + : UNIQUE '(' columnName (',' columnName)* ')' + ; + +foreignKeyConstraint + : FOREIGN KEY '(' columnName (',' columnName)* ')' + foreignKeyClause + ; + +foreignKeyClause + : REFERENCES tableName ('(' columnName (',' columnName)* ')')? + (ON DELETE referenceOption)? + (ON UPDATE referenceOption)? + ; + +referenceOption + : RESTRICT + | CASCADE + | SET NULL + | NO ACTION + | SET DEFAULT + ; + +checkConstraint + : CHECK '(' expression ')' + ; + +// ALTER statement +alterStatement + : alterTableStatement + ; + +alterTableStatement + : ALTER TABLE tableName + alterSpecification (',' alterSpecification)* + ; + +alterSpecification + : ADD COLUMN? columnDefinition + | ADD tableConstraint + | DROP COLUMN columnName + | DROP CONSTRAINT constraintName + | MODIFY COLUMN? columnDefinition + | ALTER COLUMN columnName SET DEFAULT expression + | ALTER COLUMN columnName DROP DEFAULT + ; + +// DROP statement +dropStatement + : dropTableStatement + | dropViewStatement + | dropIndexStatement + | dropDatabaseStatement + ; + +dropTableStatement + : DROP TABLE (IF EXISTS)? tableName (',' tableName)* + ; + +dropViewStatement + : DROP VIEW (IF EXISTS)? tableName (',' tableName)* + ; + +dropIndexStatement + : DROP INDEX indexName ON tableName + ; + +dropDatabaseStatement + : DROP DATABASE (IF EXISTS)? databaseName + ; + +// FROM clause and JOINs +fromClause + : FROM tableSource (',' tableSource)* + ; + +tableSource + : tablePrimary + | joinedTable + ; + +tablePrimary + : tableName (AS? alias)? + | '(' selectStatement ')' (AS? alias)? + ; + +joinedTable + : tablePrimary joinClause+ + ; + +joinType + : INNER + | LEFT OUTER? + | RIGHT OUTER? + | FULL OUTER? + ; + +joinClause + : joinTypeClause tablePrimary joinCondition + | NATURAL (INNER | LEFT | RIGHT | FULL)? JOIN tablePrimary + | CROSS JOIN tablePrimary + ; + +joinTypeClause + : INNER JOIN + | LEFT OUTER? JOIN + | RIGHT OUTER? JOIN + | FULL OUTER? JOIN + | JOIN // 这代表默认的 INNER JOIN + ; + +joinCondition + : ON expression + | USING '(' columnName (',' columnName)* ')' + ; + +// Expressions +expression + : primary + | expression IS NOT? NULL + | expression IS NOT? (TRUE | FALSE) + | NOT expression + | expression AND expression + | expression OR expression + | expression comparisonOperator expression + | expression NOT? BETWEEN expression AND expression + | expression NOT? IN ('(' expression (',' expression)* ')' | selectStatement) + | expression NOT? LIKE expression + | '(' expression ')' + | expression '+' expression + | expression '-' expression + | expression '*' expression + | expression '/' expression + | expression '%' expression + | '+' expression + | '-' expression + ; + +primary + : literal + | columnReference + | functionCall + ; + +columnReference + : (tableName '.')? columnName + ; + +functionCall + : functionName '(' (DISTINCT? expression (',' expression)*)? ')' + | CAST '(' expression AS dataType ')' + | EXTRACT '(' identifier FROM expression ')' + ; + +comparisonOperator + : '=' | '>' | '<' | '>=' | '<=' | '<>' | '!=' | '<=>' + ; + +// Common elements +value: expression; + +literal + : STRING + | INTEGER_VALUE + | DECIMAL_VALUE + | TRUE + | FALSE + | NULL + | CURRENT_TIMESTAMP + ; + +defaultValue + : literal + | '(' expression ')' + ; + +// Names and Identifiers +columnName: identifier; +tableName: (databaseName '.')? identifier; +databaseName: identifier; +indexName: identifier; +constraintName: identifier; +alias: identifier; +functionName: identifier; + +identifier + : IDENTIFIER + | quotedIdentifier + | nonReservedWord + ; + +quotedIdentifier + : BACKQUOTED_IDENTIFIER + ; + +// Data Types +dataType + : baseDataType ('(' INTEGER_VALUE (',' INTEGER_VALUE)* ')')? + ; + +baseDataType + : CHARACTER | VARCHAR | BINARY | VARBINARY + | TINYINT | SMALLINT | INTEGER | INT | BIGINT + | FLOAT | REAL | DOUBLE | DECIMAL | NUMERIC + | DATE | TIME | TIMESTAMP | DATETIME + | BOOLEAN | BOOL + | BLOB | TEXT + | JSON | XML + ; + +// Additional Keywords +UNION: [Uu][Nn][Ii][Oo][Nn]; +ALL: [Aa][Ll][Ll]; +DISTINCT: [Dd][Ii][Ss][Tt][Ii][Nn][Cc][Tt]; +EXCEPT: [Ee][Xx][Cc][Ee][Pp][Tt]; +INTERSECT: [Ii][Nn][Tt][Ee][Rr][Ss][Ee][Cc][Tt]; +CHARACTER: [Cc][Hh][Aa][Rr][Aa][Cc][Tt][Ee][Rr]; +VARCHAR: [Vv][Aa][Rr][Cc][Hh][Aa][Rr]; +BINARY: [Bb][Ii][Nn][Aa][Rr][Yy]; +VARBINARY: [Vv][Aa][Rr][Bb][Ii][Nn][Aa][Rr][Yy]; +TINYINT: [Tt][Ii][Nn][Yy][Ii][Nn][Tt]; +SMALLINT: [Ss][Mm][Aa][Ll][Ll][Ii][Nn][Tt]; +INTEGER: [Ii][Nn][Tt][Ee][Gg][Ee][Rr]; +INT: [Ii][Nn][Tt]; +BIGINT: [Bb][Ii][Gg][Ii][Nn][Tt]; +FLOAT: [Ff][Ll][Oo][Aa][Tt]; +REAL: [Rr][Ee][Aa][Ll]; +DOUBLE: [Dd][Oo][Uu][Bb][Ll][Ee]; +DECIMAL: [Dd][Ee][Cc][Ii][Mm][Aa][Ll]; +NUMERIC: [Nn][Uu][Mm][Ee][Rr][Ii][Cc]; +DATE: [Dd][Aa][Tt][Ee]; +TIME: [Tt][Ii][Mm][Ee]; +TIMESTAMP: [Tt][Ii][Mm][Ee][Ss][Tt][Aa][Mm][Pp]; +DATETIME: [Dd][Aa][Tt][Ee][Tt][Ii][Mm][Ee]; +BOOLEAN: [Bb][Oo][Oo][Ll][Ee][Aa][Nn]; +BOOL: [Bb][Oo][Oo][Ll]; +BLOB: [Bb][Ll][Oo][Bb]; +TEXT: [Tt][Ee][Xx][Tt]; +JSON: [Jj][Ss][Oo][Nn]; +XML: [Xx][Mm][Ll]; +CURRENT_TIMESTAMP: [Cc][Uu][Rr][Rr][Ee][Nn][Tt]'_'[Tt][Ii][Mm][Ee][Ss][Tt][Aa][Mm][Pp]; +CAST: [Cc][Aa][Ss][Tt]; +EXTRACT: [Ee][Xx][Tt][Rr][Aa][Cc][Tt]; +RESTRICT: [Rr][Ee][Ss][Tt][Rr][Ii][Cc][Tt]; +CASCADE: [Cc][Aa][Ss][Cc][Aa][Dd][Ee]; +NO: [Nn][Oo]; +ACTION: [Aa][Cc][Tt][Ii][Oo][Nn]; + +// Non-reserved words that can be used as identifiers +nonReservedWord + : TEMP | TEMPORARY | REPLACE | EXISTS | IF + | CONSTRAINT | COLUMN | DATABASE | INDEX + | RESTRICT | CASCADE | NO | ACTION + | CHARACTER | VARCHAR | BINARY | VARBINARY + | TINYINT | SMALLINT | INTEGER | INT | BIGINT + | FLOAT | REAL | DOUBLE | DECIMAL | NUMERIC + | DATE | TIME | TIMESTAMP | DATETIME + | BOOLEAN | BOOL | BLOB | TEXT | JSON | XML + | CHARSET | COLLATE | AUTO_INCREMENT | COMMENT + | ADD | MODIFY | ENGINE + ; + +// Lexer rules +fragment DIGIT: [0-9]; +fragment LETTER: [a-zA-Z]; +TRUE: [Tt][Rr][Uu][Ee]; +FALSE: [Ff][Aa][Ll][Ss][Ee]; + +INTEGER_VALUE + : DIGIT+ + ; + +DECIMAL_VALUE + : DIGIT+ '.' DIGIT* + | '.' DIGIT+ + ; -fragment DIGIT:[0-9]; -fragment LETTER:[a-zA-Z]; STRING : '\'' ( ~('\''|'\\') | ('\\' .) )* '\'' | '"' ( ~('"'|'\\') | ('\\' .) )* '"' - | '*' ; + IDENTIFIER - : (LETTER | DIGIT | '_')+ + : (LETTER | '_') (LETTER | DIGIT | '_')* ; BACKQUOTED_IDENTIFIER : '`' ( ~'`' | '``' )* '`' ; -SIMPLE_COMMENT: '--' ~[\r\n]* '\r'? '\n'? -> channel(HIDDEN); -BRACKETED_EMPTY_COMMENT: '/**/' -> channel(HIDDEN); -BRACKETED_COMMENT : '/*' ~[+] .*? '*/' -> channel(HIDDEN); -WS: [ \r\n\t]+ -> channel(HIDDEN); +// Comments and whitespace +SIMPLE_COMMENT + : '--' ~[\r\n]* '\r'? '\n'? -> channel(HIDDEN) + ; + +BRACKETED_COMMENT + : '/*' .*? '*/' -> channel(HIDDEN) + ; + +WS + : [ \r\n\t]+ -> channel(HIDDEN) + ; \ No newline at end of file diff --git a/core/datacap-parser/src/main/java/SqlBase.tokens b/core/datacap-parser/src/main/java/SqlBase.tokens deleted file mode 100644 index 0b5d6c9e8f..0000000000 --- a/core/datacap-parser/src/main/java/SqlBase.tokens +++ /dev/null @@ -1,20 +0,0 @@ -T__0=1 -SHOW=2 -PATHS=3 -TOPICS=4 -CONSUMERS=5 -DATABASES=6 -TABLES=7 -SELECT=8 -FROM=9 -STRING=10 -IDENTIFIER=11 -BACKQUOTED_IDENTIFIER=12 -SIMPLE_COMMENT=13 -BRACKETED_EMPTY_COMMENT=14 -BRACKETED_COMMENT=15 -WS=16 -'.'=1 -'TOPICS'=4 -'CONSUMERS'=5 -'/**/'=14 diff --git a/core/datacap-parser/src/main/java/SqlBaseLexer.tokens b/core/datacap-parser/src/main/java/SqlBaseLexer.tokens deleted file mode 100644 index 0b5d6c9e8f..0000000000 --- a/core/datacap-parser/src/main/java/SqlBaseLexer.tokens +++ /dev/null @@ -1,20 +0,0 @@ -T__0=1 -SHOW=2 -PATHS=3 -TOPICS=4 -CONSUMERS=5 -DATABASES=6 -TABLES=7 -SELECT=8 -FROM=9 -STRING=10 -IDENTIFIER=11 -BACKQUOTED_IDENTIFIER=12 -SIMPLE_COMMENT=13 -BRACKETED_EMPTY_COMMENT=14 -BRACKETED_COMMENT=15 -WS=16 -'.'=1 -'TOPICS'=4 -'CONSUMERS'=5 -'/**/'=14 diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLParseException.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLParseException.java new file mode 100644 index 0000000000..eaec3275e9 --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLParseException.java @@ -0,0 +1,15 @@ +package io.edurt.datacap.sql; + +public class SQLParseException + extends RuntimeException +{ + public SQLParseException(String message) + { + super(message); + } + + public SQLParseException(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLParser.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLParser.java new file mode 100644 index 0000000000..08a7123b6f --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLParser.java @@ -0,0 +1,39 @@ +package io.edurt.datacap.sql; + +import io.edurt.datacap.sql.parser.SqlBaseLexer; +import io.edurt.datacap.sql.parser.SqlBaseParser; +import io.edurt.datacap.sql.statement.SQLStatement; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; + +public class SQLParser +{ + public static SQLStatement parse(String sql) + { + try { + // 创建词法分析器和语法分析器 + // Create lexer and parser instance + SqlBaseLexer lexer = new SqlBaseLexer(CharStreams.fromString(sql)); + CommonTokenStream tokens = new CommonTokenStream(lexer); + SqlBaseParser parser = new SqlBaseParser(tokens); + + // 使用自定义错误监听器 + // Use custom error listener + parser.removeErrorListeners(); + parser.addErrorListener(new SQLParserErrorListener()); + + // 获取解析树 + // Get parse tree + ParseTree tree = parser.singleStatement(); + + // 访问解析树 + // Visit parse tree + SQLVisitor visitor = new SQLVisitor(); + return visitor.visit(tree); + } + catch (Exception e) { + throw new SQLParseException("Failed to parse SQL: " + e.getMessage(), e); + } + } +} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/UnderLineListener.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLParserErrorListener.java similarity index 63% rename from core/datacap-parser/src/main/java/io/edurt/datacap/sql/UnderLineListener.java rename to core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLParserErrorListener.java index cb0135bebf..5b44b6ca18 100644 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/UnderLineListener.java +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLParserErrorListener.java @@ -1,19 +1,20 @@ package io.edurt.datacap.sql; -import com.google.common.base.Preconditions; import org.antlr.v4.runtime.BaseErrorListener; import org.antlr.v4.runtime.RecognitionException; import org.antlr.v4.runtime.Recognizer; -public class UnderLineListener +public class SQLParserErrorListener extends BaseErrorListener { + @Override public void syntaxError(Recognizer recognizer, Object offendingSymbol, - int line, int charPositionInLine, + int line, + int charPositionInLine, String msg, RecognitionException e) { - Preconditions.checkState(false, "line " + line + ":" + charPositionInLine + " " + msg); + throw new SQLParseException(String.format("line %d:%d %s", line, charPositionInLine, msg)); } } diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java new file mode 100644 index 0000000000..558fe30d20 --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java @@ -0,0 +1,398 @@ +package io.edurt.datacap.sql; + +import io.edurt.datacap.sql.node.Expression; +import io.edurt.datacap.sql.node.clause.JoinClause; +import io.edurt.datacap.sql.node.clause.LimitClause; +import io.edurt.datacap.sql.node.element.OrderByElement; +import io.edurt.datacap.sql.node.element.SelectElement; +import io.edurt.datacap.sql.node.element.TableElement; +import io.edurt.datacap.sql.parser.SqlBaseBaseVisitor; +import io.edurt.datacap.sql.parser.SqlBaseParser; +import io.edurt.datacap.sql.statement.SQLStatement; +import io.edurt.datacap.sql.statement.SelectStatement; + +import java.util.ArrayList; +import java.util.List; + +public class SQLVisitor + extends SqlBaseBaseVisitor +{ + + @Override + public SQLStatement visitSingleStatement(SqlBaseParser.SingleStatementContext ctx) + { + return visit(ctx.statement(0)); + } + + @Override + public SQLStatement visitStatement(SqlBaseParser.StatementContext ctx) + { + if (ctx.selectStatement() != null) { + return visitSelectStatement(ctx.selectStatement()); + } + else if (ctx.insertStatement() != null) { + return visitInsertStatement(ctx.insertStatement()); + } + else if (ctx.updateStatement() != null) { + return visitUpdateStatement(ctx.updateStatement()); + } + else if (ctx.deleteStatement() != null) { + return visitDeleteStatement(ctx.deleteStatement()); + } + else if (ctx.createStatement() != null) { + return visitCreateStatement(ctx.createStatement()); + } + else if (ctx.alterStatement() != null) { + return visitAlterStatement(ctx.alterStatement()); + } + else if (ctx.dropStatement() != null) { + return visitDropStatement(ctx.dropStatement()); + } + else if (ctx.useStatement() != null) { + return visitUseStatement(ctx.useStatement()); + } + return null; + } + + @Override + public SQLStatement visitSelectStatement(SqlBaseParser.SelectStatementContext ctx) + { + SelectStatement statement = new SelectStatement(); + + // Parse SELECT elements + if (ctx.queryExpression().queryTerm().queryPrimary().querySpecification() != null) { + SqlBaseParser.QuerySpecificationContext querySpec = + ctx.queryExpression().queryTerm().queryPrimary().querySpecification(); + + statement.setSelectElements(processSelectElements(querySpec.selectElements())); + + // Parse FROM clause + if (querySpec.fromClause() != null) { + statement.setFromSources(processFromClause(querySpec.fromClause())); + } + + // Parse WHERE clause + if (querySpec.whereClause() != null) { + statement.setWhereClause(processExpression(querySpec.whereClause().expression())); + } + + // Parse GROUP BY clause + if (querySpec.groupByClause() != null) { + statement.setGroupByElements(visitGroupByElements(querySpec.groupByClause())); + } + + // Parse HAVING clause + if (querySpec.havingClause() != null) { + statement.setHavingClause(processExpression(querySpec.havingClause().expression())); + } + } + + // Parse ORDER BY clause + if (ctx.orderByClause() != null) { + statement.setOrderByElements(visitOrderByElements(ctx.orderByClause())); + } + + // Parse LIMIT clause + if (ctx.limitClause() != null) { + statement.setLimitClause(processLimitClause(ctx.limitClause())); + } + + return statement; + } + + @Override + public SQLStatement visitQueryExpression(SqlBaseParser.QueryExpressionContext ctx) + { + return visit(ctx.queryTerm()); + } + + @Override + public SQLStatement visitQueryTerm(SqlBaseParser.QueryTermContext ctx) + { + return visit(ctx.queryPrimary()); + } + + @Override + public SQLStatement visitQueryPrimary(SqlBaseParser.QueryPrimaryContext ctx) + { + if (ctx.querySpecification() != null) { + return visit(ctx.querySpecification()); + } + else if (ctx.queryExpression() != null) { + return visit(ctx.queryExpression()); + } + return null; + } + + @Override + public SQLStatement visitInsertStatement(SqlBaseParser.InsertStatementContext ctx) + { + // TODO: Implement insert statement parsing + return null; + } + + @Override + public SQLStatement visitUpdateStatement(SqlBaseParser.UpdateStatementContext ctx) + { + // TODO: Implement update statement parsing + return null; + } + + @Override + public SQLStatement visitDeleteStatement(SqlBaseParser.DeleteStatementContext ctx) + { + // TODO: Implement delete statement parsing + return null; + } + + @Override + public SQLStatement visitCreateStatement(SqlBaseParser.CreateStatementContext ctx) + { + // TODO: Implement create statement parsing + return null; + } + + @Override + public SQLStatement visitAlterStatement(SqlBaseParser.AlterStatementContext ctx) + { + // TODO: Implement alter statement parsing + return null; + } + + @Override + public SQLStatement visitDropStatement(SqlBaseParser.DropStatementContext ctx) + { + // TODO: Implement drop statement parsing + return null; + } + + @Override + public SQLStatement visitUseStatement(SqlBaseParser.UseStatementContext ctx) + { + // TODO: Implement use statement parsing + return null; + } + + @Override + public SQLStatement visitQuerySpecification(SqlBaseParser.QuerySpecificationContext ctx) + { + SelectStatement statement = new SelectStatement(); + statement.setSelectElements(processSelectElements(ctx.selectElements())); + + if (ctx.fromClause() != null) { + statement.setFromSources(processFromClause(ctx.fromClause())); + } + + if (ctx.whereClause() != null) { + statement.setWhereClause(processExpression(ctx.whereClause().expression())); + } + + if (ctx.groupByClause() != null) { + statement.setGroupByElements(visitGroupByElements(ctx.groupByClause())); + } + + if (ctx.havingClause() != null) { + statement.setHavingClause(processExpression(ctx.havingClause().expression())); + } + + return statement; + } + + private List processSelectElements(SqlBaseParser.SelectElementsContext ctx) + { + List elements = new ArrayList<>(); + + for (SqlBaseParser.SelectElementContext elementCtx : ctx.selectElement()) { + SelectElement element = new SelectElement(); + + if (elementCtx.columnName() != null) { + element.setColumn(elementCtx.columnName().getText()); + } + + if (elementCtx.alias() != null) { + element.setAlias(elementCtx.alias().getText()); + } + + if (elementCtx.expression() != null) { + element.setExpression(processExpression(elementCtx.expression())); + } + + elements.add(element); + } + + return elements; + } + + private List processFromClause(SqlBaseParser.FromClauseContext ctx) + { + List tables = new ArrayList<>(); + + for (SqlBaseParser.TableSourceContext sourceCtx : ctx.tableSource()) { + TableElement table = new TableElement(); + + // 普通获取主表信息 + // Get the primary table information + if (sourceCtx.tablePrimary() != null) { + SqlBaseParser.TablePrimaryContext primaryCtx = sourceCtx.tablePrimary(); + + // 处理子查询 + // Handle subquery + if (primaryCtx.selectStatement() != null) { + // 处理子查询的别名 + // Handle the alias of the subquery + if (primaryCtx.alias() != null) { + table.setAlias(primaryCtx.alias().getText()); + } + // 可以选择存储子查询的SelectStatement + SelectStatement subquery = (SelectStatement) visit(primaryCtx.selectStatement()); + table.setSubquery(subquery); + } + // 处理普通表 + // Handle normal tables + else if (primaryCtx.tableName() != null) { + table.setTableName(primaryCtx.tableName().getText()); + if (primaryCtx.alias() != null) { + table.setAlias(primaryCtx.alias().getText()); + } + } + } + + if (sourceCtx.joinedTable() != null) { + List joins = new ArrayList<>(); + + // 从 joinedTable 的 tablePrimary 中获取主表信息 + // Get the primary table information from the tablePrimary of joinedTable + SqlBaseParser.TablePrimaryContext primaryCtx = sourceCtx.joinedTable().tablePrimary(); + if (primaryCtx != null && primaryCtx.tableName() != null) { + table.setTableName(primaryCtx.tableName().getText()); + if (primaryCtx.alias() != null) { + table.setAlias(primaryCtx.alias().getText()); + } + } + + // 处理 joins + // Handle joins + for (SqlBaseParser.JoinClauseContext joinCtx : sourceCtx.joinedTable().joinClause()) { + JoinClause join = processJoinClause(joinCtx); + joins.add(join); + } + table.setJoins(joins); + } + + tables.add(table); + } + + return tables; + } + + private JoinClause processJoinClause(SqlBaseParser.JoinClauseContext ctx) + { + JoinClause join = new JoinClause(); + + if (ctx.joinTypeClause() != null) { + if (ctx.joinTypeClause().INNER() != null) { + join.setJoinType(JoinClause.JoinType.INNER); + } + else if (ctx.joinTypeClause().LEFT() != null) { + join.setJoinType(JoinClause.JoinType.LEFT); + } + else if (ctx.joinTypeClause().RIGHT() != null) { + join.setJoinType(JoinClause.JoinType.RIGHT); + } + else if (ctx.joinTypeClause().FULL() != null) { + join.setJoinType(JoinClause.JoinType.FULL); + } + } + + TableElement rightTable = new TableElement(); + rightTable.setTableName(ctx.tablePrimary().tableName().getText()); + if (ctx.tablePrimary().alias() != null) { + rightTable.setAlias(ctx.tablePrimary().alias().getText()); + } + join.setRightTable(rightTable); + + if (ctx.joinCondition() != null) { + if (ctx.joinCondition().ON() != null) { + join.setCondition(processExpression(ctx.joinCondition().expression())); + } + } + + return join; + } + + private Expression processExpression(SqlBaseParser.ExpressionContext ctx) + { + Expression expr = new Expression(); + + if (ctx.primary() != null) { + if (ctx.primary().literal() != null) { + expr.setType(Expression.ExpressionType.LITERAL); + expr.setValue(ctx.primary().literal().getText()); + } + else if (ctx.primary().columnReference() != null) { + expr.setType(Expression.ExpressionType.COLUMN_REFERENCE); + expr.setValue(ctx.primary().columnReference().getText()); + } + else if (ctx.primary().functionCall() != null) { + expr.setType(Expression.ExpressionType.FUNCTION_CALL); + expr.setValue(ctx.primary().functionCall().getText()); + } + } + else { + expr.setType(Expression.ExpressionType.BINARY_OP); + List children = new ArrayList<>(); + + if (ctx.expression().size() > 1) { + for (SqlBaseParser.ExpressionContext childCtx : ctx.expression()) { + children.add(processExpression(childCtx)); + } + } + expr.setChildren(children); + } + + return expr; + } + + private List visitGroupByElements(SqlBaseParser.GroupByClauseContext ctx) + { + List groupByElements = new ArrayList<>(); + + for (SqlBaseParser.GroupByElementContext elementCtx : ctx.groupByElement()) { + groupByElements.add(processExpression(elementCtx.expression())); + } + + return groupByElements; + } + + private List visitOrderByElements(SqlBaseParser.OrderByClauseContext ctx) + { + List orderByElements = new ArrayList<>(); + + for (SqlBaseParser.OrderByElementContext elementCtx : ctx.orderByElement()) { + OrderByElement element = new OrderByElement(); + element.setExpression(processExpression(elementCtx.expression())); + element.setAscending(elementCtx.DESC() == null); + orderByElements.add(element); + } + + return orderByElements; + } + + private LimitClause processLimitClause(SqlBaseParser.LimitClauseContext ctx) + { + LimitClause limit = new LimitClause(); + + if (ctx.INTEGER_VALUE().size() > 1) { + limit.setOffset(Long.parseLong(ctx.INTEGER_VALUE(0).getText())); + limit.setLimit(Long.parseLong(ctx.INTEGER_VALUE(1).getText())); + } + else { + limit.setLimit(Long.parseLong(ctx.INTEGER_VALUE(0).getText())); + if (ctx.OFFSET() != null) { + limit.setOffset(Long.parseLong(ctx.INTEGER_VALUE(1).getText())); + } + } + + return limit; + } +} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBase.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBase.java deleted file mode 100644 index 2a6d026916..0000000000 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBase.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.edurt.datacap.sql; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.ToString; - -import java.util.ArrayList; -import java.util.List; - -@Data -@ToString -@NoArgsConstructor -@AllArgsConstructor -@SuppressFBWarnings(value = {"EI_EXPOSE_REP", "EI_EXPOSE_REPR", "EI_EXPOSE_REP2"}) -public class SqlBase -{ - private String token; - private String childToken; - private List columns = new ArrayList<>(); - private String table; - private boolean successful = false; - private String message; -} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBaseFormatter.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBaseFormatter.java deleted file mode 100644 index a45ab4908d..0000000000 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBaseFormatter.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.edurt.datacap.sql; - -import com.google.common.base.Preconditions; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import io.edurt.datacap.sql.parser.SqlBaseLexer; -import io.edurt.datacap.sql.parser.SqlBaseParser; -import lombok.Getter; -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.CharStreams; -import org.antlr.v4.runtime.CommonTokenStream; -import org.antlr.v4.runtime.atn.PredictionMode; -import org.antlr.v4.runtime.tree.ParseTree; -import org.apache.commons.lang3.ObjectUtils; - -@SuppressFBWarnings(value = {"EI_EXPOSE_REP"}) -public class SqlBaseFormatter -{ - private final String sql; - - @Getter - private SqlBase parseResult; - - public SqlBaseFormatter(String sql) - { - this.sql = sql; - this.parseResult = new SqlBase(); - this.initialize(); - } - - private SqlBase initialize() - { - CharStream stream = CharStreams.fromString(this.sql); - SqlBaseLexer lexer = new SqlBaseLexer(new SqlCaseInsensitiveStream(stream)); - lexer.removeErrorListeners(); - lexer.addErrorListener(new UnderLineListener()); - CommonTokenStream tokens = new CommonTokenStream(lexer); - SqlBaseParser parser = new SqlBaseParser(tokens); - parser.removeErrorListeners(); - parser.addErrorListener(new UnderLineListener()); - parser.getInterpreter().setPredictionMode(PredictionMode.SLL); - - ParseTree tree; - try { - tree = parser.singleStatement(); - } - catch (Exception ex) { - this.parseResult.setMessage(ex.getMessage()); - this.parseResult.setSuccessful(false); - return this.parseResult; - } - - SqlBaseVisitor sqlBaseVisitor = new SqlBaseVisitor(); - if (ObjectUtils.isNotEmpty(tree)) { - this.parseResult = sqlBaseVisitor.visit(tree); - } - else { - Preconditions.checkArgument(false, "Not support sql"); - } - return this.parseResult; - } -} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBaseToken.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBaseToken.java deleted file mode 100644 index 297c65e6e8..0000000000 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBaseToken.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.edurt.datacap.sql; - -public enum SqlBaseToken -{ - SHOW, - PATHS, - SELECT, - // ------ Kafka ------ - TOPICS, - CONSUMERS, -} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBaseVisitor.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBaseVisitor.java deleted file mode 100644 index a5361369c0..0000000000 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlBaseVisitor.java +++ /dev/null @@ -1,136 +0,0 @@ -package io.edurt.datacap.sql; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import io.edurt.datacap.sql.parser.SqlBaseParser; -import org.antlr.v4.runtime.tree.ErrorNode; -import org.antlr.v4.runtime.tree.ParseTree; -import org.antlr.v4.runtime.tree.ParseTreeVisitor; -import org.antlr.v4.runtime.tree.RuleNode; -import org.antlr.v4.runtime.tree.TerminalNode; -import org.apache.commons.lang3.exception.ExceptionUtils; - -import java.util.Arrays; - -@SuppressFBWarnings(value = {"EI_EXPOSE_REP"}) -public class SqlBaseVisitor - implements ParseTreeVisitor -{ - private SqlBase configure; - - public SqlBaseVisitor() - { - configure = new SqlBase(); - } - - @Override - public SqlBase visit(ParseTree parseTree) - { - int childCount = parseTree.getChildCount(); - for (int i = 0; i < childCount; i++) { - ParseTree child = parseTree.getChild(i); - if (child instanceof SqlBaseParser.StatementContext) { - SqlBaseParser.StatementContext statementContext = (SqlBaseParser.StatementContext) child; - this.handlerWithStatement(statementContext); - } - } - return this.configure; - } - - @Override - public SqlBase visitChildren(RuleNode ruleNode) - { - return this.configure; - } - - @Override - public SqlBase visitTerminal(TerminalNode terminalNode) - { - return this.configure; - } - - @Override - public SqlBase visitErrorNode(ErrorNode errorNode) - { - this.configure.setSuccessful(false); - this.configure.setMessage(errorNode.getText()); - return configure; - } - - private void handlerWithStatement(SqlBaseParser.StatementContext statementContext) - { - int childCount = statementContext.getChildCount(); - int i = 0; - for (; i < childCount; i++) { - ParseTree child = statementContext.getChild(i); - /* Kafka Statement */ - if (child instanceof SqlBaseParser.KafkaStatementContext) { - this.handlerWithKafkaStatement((SqlBaseParser.KafkaStatementContext) child); - } - else if (child instanceof SqlBaseParser.ColumnStatementContext) { - configure.setColumns(Arrays.asList(child.getText())); - } - else if (child instanceof SqlBaseParser.FromClauseContext) { - configure.setTable(child.getChild(1).getText()); - } - else if (child instanceof SqlBaseParser.ChildPathStatementContext) { - this.handlerWithChildPathStatementContext((SqlBaseParser.ChildPathStatementContext) child); - } - else if (child instanceof TerminalNode) { - this.applyToken(child.getText(), false); - } - } - } - - private void handlerWithChildPathStatementContext(SqlBaseParser.ChildPathStatementContext context) - { - int childCount = context.getChildCount(); - int i = 0; - for (; i < childCount; i++) { - ParseTree child = context.getChild(i); - if (child instanceof SqlBaseParser.FromClauseContext) { - this.configure.setTable(child.getChild(1).getText()); - } - else if (child instanceof TerminalNode) { - this.applyToken(child.getText(), true); - } - } - } - - private void handlerWithKafkaStatement(SqlBaseParser.KafkaStatementContext context) - { - ParseTree node = context.getChild(0); - if (node instanceof SqlBaseParser.KafkaQueryStatementContext) { - ParseTree queryNode = node.getChild(0); - if (queryNode instanceof SqlBaseParser.KafkaQueryTopicStatementContext - | queryNode instanceof SqlBaseParser.KafkaQueryConsumerStatementContext) { - int count = queryNode.getChildCount(); - this.applyToken(queryNode.getChild(0).getText(), false); - this.applyToken(queryNode.getChild(1).getText(), true); - // If the total number is greater than 2, the mark specifies the topic, which is the table name - if (count > 2) { - ParseTree fromNode = queryNode.getChild(count - 1); - if (fromNode instanceof SqlBaseParser.FromClauseContext) { - configure.setTable(fromNode.getChild(1).getText()); - } - } - } - } - } - - private void applyToken(String token, boolean isChild) - { - try { - if (isChild) { - this.configure.setChildToken(token.toUpperCase()); - } - else { - this.configure.setToken(token.toUpperCase()); - } - configure.setSuccessful(true); - } - catch (Exception exception) { - configure.setSuccessful(false); - configure.setMessage(ExceptionUtils.getMessage(exception)); - } - } -} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlCaseInsensitiveStream.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlCaseInsensitiveStream.java deleted file mode 100644 index 4e8c78ee4f..0000000000 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SqlCaseInsensitiveStream.java +++ /dev/null @@ -1,78 +0,0 @@ -package io.edurt.datacap.sql; - -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.IntStream; -import org.antlr.v4.runtime.misc.Interval; - -public class SqlCaseInsensitiveStream - implements CharStream -{ - private final CharStream stream; - - public SqlCaseInsensitiveStream(CharStream stream) - { - this.stream = stream; - } - - @Override - public String getText(Interval interval) - { - return stream.getText(interval); - } - - @Override - public void consume() - { - stream.consume(); - } - - @Override - public int LA(int i) - { - int result = stream.LA(i); - - switch (result) { - case 0: - case IntStream.EOF: - return result; - default: - return Character.toUpperCase(result); - } - } - - @Override - public int mark() - { - return stream.mark(); - } - - @Override - public void release(int marker) - { - stream.release(marker); - } - - @Override - public int index() - { - return stream.index(); - } - - @Override - public void seek(int index) - { - stream.seek(index); - } - - @Override - public int size() - { - return stream.size(); - } - - @Override - public String getSourceName() - { - return stream.getSourceName(); - } -} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/Expression.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/Expression.java new file mode 100644 index 0000000000..c9eb2c427c --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/Expression.java @@ -0,0 +1,20 @@ +package io.edurt.datacap.sql.node; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class Expression +{ + private ExpressionType type; + private Object value; + private List children; + + public enum ExpressionType + { + LITERAL, COLUMN_REFERENCE, FUNCTION_CALL, BINARY_OP, UNARY_OP + } +} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/clause/JoinClause.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/clause/JoinClause.java new file mode 100644 index 0000000000..f234d3c649 --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/clause/JoinClause.java @@ -0,0 +1,20 @@ +package io.edurt.datacap.sql.node.clause; + +import io.edurt.datacap.sql.node.Expression; +import io.edurt.datacap.sql.node.element.TableElement; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class JoinClause +{ + private JoinType joinType; + private TableElement rightTable; + private Expression condition; + + public enum JoinType + { + INNER, LEFT, RIGHT, FULL, CROSS, NATURAL + } +} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/clause/LimitClause.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/clause/LimitClause.java new file mode 100644 index 0000000000..fb776a8c38 --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/clause/LimitClause.java @@ -0,0 +1,12 @@ +package io.edurt.datacap.sql.node.clause; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class LimitClause +{ + private long limit; + private long offset; +} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/element/OrderByElement.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/element/OrderByElement.java new file mode 100644 index 0000000000..a9948460df --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/element/OrderByElement.java @@ -0,0 +1,13 @@ +package io.edurt.datacap.sql.node.element; + +import io.edurt.datacap.sql.node.Expression; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class OrderByElement +{ + private Expression expression; + private boolean ascending; +} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/element/SelectElement.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/element/SelectElement.java new file mode 100644 index 0000000000..d1970fdac7 --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/element/SelectElement.java @@ -0,0 +1,14 @@ +package io.edurt.datacap.sql.node.element; + +import io.edurt.datacap.sql.node.Expression; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class SelectElement +{ + private String column; + private String alias; + private Expression expression; +} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/element/TableElement.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/element/TableElement.java new file mode 100644 index 0000000000..b6663e885f --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/element/TableElement.java @@ -0,0 +1,18 @@ +package io.edurt.datacap.sql.node.element; + +import io.edurt.datacap.sql.node.clause.JoinClause; +import io.edurt.datacap.sql.statement.SelectStatement; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class TableElement +{ + private String tableName; + private String alias; + private List joins; + private SelectStatement subquery; +} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBase.interp b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBase.interp deleted file mode 100644 index b46bdc67ef..0000000000 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBase.interp +++ /dev/null @@ -1,55 +0,0 @@ -token literal names: -null -'.' -null -null -'TOPICS' -'CONSUMERS' -null -null -null -null -null -null -null -null -'/**/' -null -null - -token symbolic names: -null -null -SHOW -PATHS -TOPICS -CONSUMERS -DATABASES -TABLES -SELECT -FROM -STRING -IDENTIFIER -BACKQUOTED_IDENTIFIER -SIMPLE_COMMENT -BRACKETED_EMPTY_COMMENT -BRACKETED_COMMENT -WS - -rule names: -singleStatement -statement -kafkaQueryTopicStatement -kafkaQueryConsumerStatement -kafkaQueryStatement -kafkaStatement -childPathStatement -columnStatement -fromClause -tableName -identifier -quotedIdentifier - - -atn: -[4, 1, 16, 92, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 1, 0, 5, 0, 26, 8, 0, 10, 0, 12, 0, 29, 9, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 38, 8, 1, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 44, 8, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 56, 8, 3, 1, 4, 1, 4, 3, 4, 60, 8, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 3, 6, 67, 8, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 5, 9, 77, 8, 9, 10, 9, 12, 9, 80, 9, 9, 1, 10, 1, 10, 1, 10, 5, 10, 85, 8, 10, 10, 10, 12, 10, 88, 9, 10, 1, 11, 1, 11, 1, 11, 0, 0, 12, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 0, 0, 92, 0, 27, 1, 0, 0, 0, 2, 37, 1, 0, 0, 0, 4, 43, 1, 0, 0, 0, 6, 55, 1, 0, 0, 0, 8, 59, 1, 0, 0, 0, 10, 61, 1, 0, 0, 0, 12, 66, 1, 0, 0, 0, 14, 68, 1, 0, 0, 0, 16, 70, 1, 0, 0, 0, 18, 73, 1, 0, 0, 0, 20, 86, 1, 0, 0, 0, 22, 89, 1, 0, 0, 0, 24, 26, 3, 2, 1, 0, 25, 24, 1, 0, 0, 0, 26, 29, 1, 0, 0, 0, 27, 25, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 1, 1, 0, 0, 0, 29, 27, 1, 0, 0, 0, 30, 31, 5, 2, 0, 0, 31, 38, 3, 12, 6, 0, 32, 33, 5, 8, 0, 0, 33, 34, 3, 14, 7, 0, 34, 35, 3, 16, 8, 0, 35, 38, 1, 0, 0, 0, 36, 38, 3, 10, 5, 0, 37, 30, 1, 0, 0, 0, 37, 32, 1, 0, 0, 0, 37, 36, 1, 0, 0, 0, 38, 3, 1, 0, 0, 0, 39, 40, 5, 2, 0, 0, 40, 44, 5, 4, 0, 0, 41, 42, 5, 2, 0, 0, 42, 44, 5, 6, 0, 0, 43, 39, 1, 0, 0, 0, 43, 41, 1, 0, 0, 0, 44, 5, 1, 0, 0, 0, 45, 46, 5, 2, 0, 0, 46, 56, 5, 5, 0, 0, 47, 48, 5, 2, 0, 0, 48, 49, 5, 5, 0, 0, 49, 56, 3, 16, 8, 0, 50, 51, 5, 2, 0, 0, 51, 56, 5, 7, 0, 0, 52, 53, 5, 2, 0, 0, 53, 54, 5, 7, 0, 0, 54, 56, 3, 16, 8, 0, 55, 45, 1, 0, 0, 0, 55, 47, 1, 0, 0, 0, 55, 50, 1, 0, 0, 0, 55, 52, 1, 0, 0, 0, 56, 7, 1, 0, 0, 0, 57, 60, 3, 4, 2, 0, 58, 60, 3, 6, 3, 0, 59, 57, 1, 0, 0, 0, 59, 58, 1, 0, 0, 0, 60, 9, 1, 0, 0, 0, 61, 62, 3, 8, 4, 0, 62, 11, 1, 0, 0, 0, 63, 67, 5, 3, 0, 0, 64, 65, 5, 3, 0, 0, 65, 67, 3, 16, 8, 0, 66, 63, 1, 0, 0, 0, 66, 64, 1, 0, 0, 0, 67, 13, 1, 0, 0, 0, 68, 69, 3, 20, 10, 0, 69, 15, 1, 0, 0, 0, 70, 71, 5, 9, 0, 0, 71, 72, 3, 18, 9, 0, 72, 17, 1, 0, 0, 0, 73, 78, 3, 20, 10, 0, 74, 75, 5, 1, 0, 0, 75, 77, 3, 20, 10, 0, 76, 74, 1, 0, 0, 0, 77, 80, 1, 0, 0, 0, 78, 76, 1, 0, 0, 0, 78, 79, 1, 0, 0, 0, 79, 19, 1, 0, 0, 0, 80, 78, 1, 0, 0, 0, 81, 85, 5, 11, 0, 0, 82, 85, 5, 10, 0, 0, 83, 85, 3, 22, 11, 0, 84, 81, 1, 0, 0, 0, 84, 82, 1, 0, 0, 0, 84, 83, 1, 0, 0, 0, 85, 88, 1, 0, 0, 0, 86, 84, 1, 0, 0, 0, 86, 87, 1, 0, 0, 0, 87, 21, 1, 0, 0, 0, 88, 86, 1, 0, 0, 0, 89, 90, 5, 12, 0, 0, 90, 23, 1, 0, 0, 0, 9, 27, 37, 43, 55, 59, 66, 78, 84, 86] \ No newline at end of file diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseBaseListener.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseBaseListener.java deleted file mode 100644 index 65b505500d..0000000000 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseBaseListener.java +++ /dev/null @@ -1,184 +0,0 @@ -// Generated from io/edurt/datacap/sql/parser/SqlBase.g4 by ANTLR 4.12.0 -package io.edurt.datacap.sql.parser; - -import org.antlr.v4.runtime.ParserRuleContext; -import org.antlr.v4.runtime.tree.ErrorNode; -import org.antlr.v4.runtime.tree.TerminalNode; - -/** - * This class provides an empty implementation of {@link SqlBaseListener}, - * which can be extended to create a listener which only needs to handle a subset - * of the available methods. - */ -@SuppressWarnings("CheckReturnValue") -public class SqlBaseBaseListener implements SqlBaseListener { - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterSingleStatement(SqlBaseParser.SingleStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitSingleStatement(SqlBaseParser.SingleStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterStatement(SqlBaseParser.StatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitStatement(SqlBaseParser.StatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterKafkaQueryTopicStatement(SqlBaseParser.KafkaQueryTopicStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitKafkaQueryTopicStatement(SqlBaseParser.KafkaQueryTopicStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterKafkaQueryConsumerStatement(SqlBaseParser.KafkaQueryConsumerStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitKafkaQueryConsumerStatement(SqlBaseParser.KafkaQueryConsumerStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterKafkaQueryStatement(SqlBaseParser.KafkaQueryStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitKafkaQueryStatement(SqlBaseParser.KafkaQueryStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterKafkaStatement(SqlBaseParser.KafkaStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitKafkaStatement(SqlBaseParser.KafkaStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterChildPathStatement(SqlBaseParser.ChildPathStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitChildPathStatement(SqlBaseParser.ChildPathStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterColumnStatement(SqlBaseParser.ColumnStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitColumnStatement(SqlBaseParser.ColumnStatementContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterFromClause(SqlBaseParser.FromClauseContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitFromClause(SqlBaseParser.FromClauseContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterTableName(SqlBaseParser.TableNameContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitTableName(SqlBaseParser.TableNameContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterIdentifier(SqlBaseParser.IdentifierContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitIdentifier(SqlBaseParser.IdentifierContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterQuotedIdentifier(SqlBaseParser.QuotedIdentifierContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitQuotedIdentifier(SqlBaseParser.QuotedIdentifierContext ctx) { } - - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void enterEveryRule(ParserRuleContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void exitEveryRule(ParserRuleContext ctx) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void visitTerminal(TerminalNode node) { } - /** - * {@inheritDoc} - * - *

The default implementation does nothing.

- */ - @Override public void visitErrorNode(ErrorNode node) { } -} \ No newline at end of file diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseBaseVisitor.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseBaseVisitor.java deleted file mode 100644 index 0b54b22aa2..0000000000 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseBaseVisitor.java +++ /dev/null @@ -1,99 +0,0 @@ -// Generated from io/edurt/datacap/sql/parser/SqlBase.g4 by ANTLR 4.12.0 -package io.edurt.datacap.sql.parser; -import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; - -/** - * This class provides an empty implementation of {@link SqlBaseVisitor}, - * which can be extended to create a visitor which only needs to handle a subset - * of the available methods. - * - * @param The return type of the visit operation. Use {@link Void} for - * operations with no return type. - */ -@SuppressWarnings("CheckReturnValue") -public class SqlBaseBaseVisitor extends AbstractParseTreeVisitor implements SqlBaseVisitor { - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitSingleStatement(SqlBaseParser.SingleStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitStatement(SqlBaseParser.StatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitKafkaQueryTopicStatement(SqlBaseParser.KafkaQueryTopicStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitKafkaQueryConsumerStatement(SqlBaseParser.KafkaQueryConsumerStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitKafkaQueryStatement(SqlBaseParser.KafkaQueryStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitKafkaStatement(SqlBaseParser.KafkaStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitChildPathStatement(SqlBaseParser.ChildPathStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitColumnStatement(SqlBaseParser.ColumnStatementContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitFromClause(SqlBaseParser.FromClauseContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitTableName(SqlBaseParser.TableNameContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitIdentifier(SqlBaseParser.IdentifierContext ctx) { return visitChildren(ctx); } - /** - * {@inheritDoc} - * - *

The default implementation returns the result of calling - * {@link #visitChildren} on {@code ctx}.

- */ - @Override public T visitQuotedIdentifier(SqlBaseParser.QuotedIdentifierContext ctx) { return visitChildren(ctx); } -} \ No newline at end of file diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseLexer.interp b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseLexer.interp deleted file mode 100644 index d8822ced22..0000000000 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseLexer.interp +++ /dev/null @@ -1,67 +0,0 @@ -token literal names: -null -'.' -null -null -'TOPICS' -'CONSUMERS' -null -null -null -null -null -null -null -null -'/**/' -null -null - -token symbolic names: -null -null -SHOW -PATHS -TOPICS -CONSUMERS -DATABASES -TABLES -SELECT -FROM -STRING -IDENTIFIER -BACKQUOTED_IDENTIFIER -SIMPLE_COMMENT -BRACKETED_EMPTY_COMMENT -BRACKETED_COMMENT -WS - -rule names: -T__0 -SHOW -PATHS -TOPICS -CONSUMERS -DATABASES -TABLES -SELECT -FROM -DIGIT -LETTER -STRING -IDENTIFIER -BACKQUOTED_IDENTIFIER -SIMPLE_COMMENT -BRACKETED_EMPTY_COMMENT -BRACKETED_COMMENT -WS - -channel names: -DEFAULT_TOKEN_CHANNEL -HIDDEN - -mode names: -DEFAULT_MODE - -atn: -[4, 0, 16, 187, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 105, 8, 11, 10, 11, 12, 11, 108, 9, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 115, 8, 11, 10, 11, 12, 11, 118, 9, 11, 1, 11, 1, 11, 3, 11, 122, 8, 11, 1, 12, 1, 12, 1, 12, 4, 12, 127, 8, 12, 11, 12, 12, 12, 128, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 135, 8, 13, 10, 13, 12, 13, 138, 9, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 5, 14, 146, 8, 14, 10, 14, 12, 14, 149, 9, 14, 1, 14, 3, 14, 152, 8, 14, 1, 14, 3, 14, 155, 8, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 5, 16, 171, 8, 16, 10, 16, 12, 16, 174, 9, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 4, 17, 182, 8, 17, 11, 17, 12, 17, 183, 1, 17, 1, 17, 1, 172, 0, 18, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 0, 21, 0, 23, 10, 25, 11, 27, 12, 29, 13, 31, 14, 33, 15, 35, 16, 1, 0, 24, 2, 0, 83, 83, 115, 115, 2, 0, 72, 72, 104, 104, 2, 0, 79, 79, 111, 111, 2, 0, 87, 87, 119, 119, 2, 0, 80, 80, 112, 112, 2, 0, 65, 65, 97, 97, 2, 0, 84, 84, 116, 116, 2, 0, 68, 68, 100, 100, 2, 0, 66, 66, 98, 98, 2, 0, 69, 69, 115, 115, 2, 0, 76, 76, 108, 108, 2, 0, 69, 69, 101, 101, 2, 0, 67, 67, 99, 99, 2, 0, 70, 70, 102, 102, 2, 0, 82, 82, 114, 114, 2, 0, 77, 77, 109, 109, 1, 0, 48, 57, 2, 0, 65, 90, 97, 122, 2, 0, 39, 39, 92, 92, 2, 0, 34, 34, 92, 92, 1, 0, 96, 96, 2, 0, 10, 10, 13, 13, 1, 0, 43, 43, 3, 0, 9, 10, 13, 13, 32, 32, 200, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 1, 37, 1, 0, 0, 0, 3, 39, 1, 0, 0, 0, 5, 44, 1, 0, 0, 0, 7, 50, 1, 0, 0, 0, 9, 57, 1, 0, 0, 0, 11, 67, 1, 0, 0, 0, 13, 77, 1, 0, 0, 0, 15, 84, 1, 0, 0, 0, 17, 91, 1, 0, 0, 0, 19, 96, 1, 0, 0, 0, 21, 98, 1, 0, 0, 0, 23, 121, 1, 0, 0, 0, 25, 126, 1, 0, 0, 0, 27, 130, 1, 0, 0, 0, 29, 141, 1, 0, 0, 0, 31, 158, 1, 0, 0, 0, 33, 165, 1, 0, 0, 0, 35, 181, 1, 0, 0, 0, 37, 38, 5, 46, 0, 0, 38, 2, 1, 0, 0, 0, 39, 40, 7, 0, 0, 0, 40, 41, 7, 1, 0, 0, 41, 42, 7, 2, 0, 0, 42, 43, 7, 3, 0, 0, 43, 4, 1, 0, 0, 0, 44, 45, 7, 4, 0, 0, 45, 46, 7, 5, 0, 0, 46, 47, 7, 6, 0, 0, 47, 48, 7, 1, 0, 0, 48, 49, 7, 0, 0, 0, 49, 6, 1, 0, 0, 0, 50, 51, 5, 84, 0, 0, 51, 52, 5, 79, 0, 0, 52, 53, 5, 80, 0, 0, 53, 54, 5, 73, 0, 0, 54, 55, 5, 67, 0, 0, 55, 56, 5, 83, 0, 0, 56, 8, 1, 0, 0, 0, 57, 58, 5, 67, 0, 0, 58, 59, 5, 79, 0, 0, 59, 60, 5, 78, 0, 0, 60, 61, 5, 83, 0, 0, 61, 62, 5, 85, 0, 0, 62, 63, 5, 77, 0, 0, 63, 64, 5, 69, 0, 0, 64, 65, 5, 82, 0, 0, 65, 66, 5, 83, 0, 0, 66, 10, 1, 0, 0, 0, 67, 68, 7, 7, 0, 0, 68, 69, 7, 5, 0, 0, 69, 70, 7, 6, 0, 0, 70, 71, 7, 5, 0, 0, 71, 72, 7, 8, 0, 0, 72, 73, 7, 5, 0, 0, 73, 74, 7, 0, 0, 0, 74, 75, 7, 9, 0, 0, 75, 76, 7, 0, 0, 0, 76, 12, 1, 0, 0, 0, 77, 78, 7, 6, 0, 0, 78, 79, 7, 5, 0, 0, 79, 80, 7, 8, 0, 0, 80, 81, 7, 10, 0, 0, 81, 82, 7, 11, 0, 0, 82, 83, 7, 0, 0, 0, 83, 14, 1, 0, 0, 0, 84, 85, 7, 0, 0, 0, 85, 86, 7, 11, 0, 0, 86, 87, 7, 10, 0, 0, 87, 88, 7, 11, 0, 0, 88, 89, 7, 12, 0, 0, 89, 90, 7, 6, 0, 0, 90, 16, 1, 0, 0, 0, 91, 92, 7, 13, 0, 0, 92, 93, 7, 14, 0, 0, 93, 94, 7, 2, 0, 0, 94, 95, 7, 15, 0, 0, 95, 18, 1, 0, 0, 0, 96, 97, 7, 16, 0, 0, 97, 20, 1, 0, 0, 0, 98, 99, 7, 17, 0, 0, 99, 22, 1, 0, 0, 0, 100, 106, 5, 39, 0, 0, 101, 105, 8, 18, 0, 0, 102, 103, 5, 92, 0, 0, 103, 105, 9, 0, 0, 0, 104, 101, 1, 0, 0, 0, 104, 102, 1, 0, 0, 0, 105, 108, 1, 0, 0, 0, 106, 104, 1, 0, 0, 0, 106, 107, 1, 0, 0, 0, 107, 109, 1, 0, 0, 0, 108, 106, 1, 0, 0, 0, 109, 122, 5, 39, 0, 0, 110, 116, 5, 34, 0, 0, 111, 115, 8, 19, 0, 0, 112, 113, 5, 92, 0, 0, 113, 115, 9, 0, 0, 0, 114, 111, 1, 0, 0, 0, 114, 112, 1, 0, 0, 0, 115, 118, 1, 0, 0, 0, 116, 114, 1, 0, 0, 0, 116, 117, 1, 0, 0, 0, 117, 119, 1, 0, 0, 0, 118, 116, 1, 0, 0, 0, 119, 122, 5, 34, 0, 0, 120, 122, 5, 42, 0, 0, 121, 100, 1, 0, 0, 0, 121, 110, 1, 0, 0, 0, 121, 120, 1, 0, 0, 0, 122, 24, 1, 0, 0, 0, 123, 127, 3, 21, 10, 0, 124, 127, 3, 19, 9, 0, 125, 127, 5, 95, 0, 0, 126, 123, 1, 0, 0, 0, 126, 124, 1, 0, 0, 0, 126, 125, 1, 0, 0, 0, 127, 128, 1, 0, 0, 0, 128, 126, 1, 0, 0, 0, 128, 129, 1, 0, 0, 0, 129, 26, 1, 0, 0, 0, 130, 136, 5, 96, 0, 0, 131, 135, 8, 20, 0, 0, 132, 133, 5, 96, 0, 0, 133, 135, 5, 96, 0, 0, 134, 131, 1, 0, 0, 0, 134, 132, 1, 0, 0, 0, 135, 138, 1, 0, 0, 0, 136, 134, 1, 0, 0, 0, 136, 137, 1, 0, 0, 0, 137, 139, 1, 0, 0, 0, 138, 136, 1, 0, 0, 0, 139, 140, 5, 96, 0, 0, 140, 28, 1, 0, 0, 0, 141, 142, 5, 45, 0, 0, 142, 143, 5, 45, 0, 0, 143, 147, 1, 0, 0, 0, 144, 146, 8, 21, 0, 0, 145, 144, 1, 0, 0, 0, 146, 149, 1, 0, 0, 0, 147, 145, 1, 0, 0, 0, 147, 148, 1, 0, 0, 0, 148, 151, 1, 0, 0, 0, 149, 147, 1, 0, 0, 0, 150, 152, 5, 13, 0, 0, 151, 150, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 154, 1, 0, 0, 0, 153, 155, 5, 10, 0, 0, 154, 153, 1, 0, 0, 0, 154, 155, 1, 0, 0, 0, 155, 156, 1, 0, 0, 0, 156, 157, 6, 14, 0, 0, 157, 30, 1, 0, 0, 0, 158, 159, 5, 47, 0, 0, 159, 160, 5, 42, 0, 0, 160, 161, 5, 42, 0, 0, 161, 162, 5, 47, 0, 0, 162, 163, 1, 0, 0, 0, 163, 164, 6, 15, 0, 0, 164, 32, 1, 0, 0, 0, 165, 166, 5, 47, 0, 0, 166, 167, 5, 42, 0, 0, 167, 168, 1, 0, 0, 0, 168, 172, 8, 22, 0, 0, 169, 171, 9, 0, 0, 0, 170, 169, 1, 0, 0, 0, 171, 174, 1, 0, 0, 0, 172, 173, 1, 0, 0, 0, 172, 170, 1, 0, 0, 0, 173, 175, 1, 0, 0, 0, 174, 172, 1, 0, 0, 0, 175, 176, 5, 42, 0, 0, 176, 177, 5, 47, 0, 0, 177, 178, 1, 0, 0, 0, 178, 179, 6, 16, 0, 0, 179, 34, 1, 0, 0, 0, 180, 182, 7, 23, 0, 0, 181, 180, 1, 0, 0, 0, 182, 183, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 183, 184, 1, 0, 0, 0, 184, 185, 1, 0, 0, 0, 185, 186, 6, 17, 0, 0, 186, 36, 1, 0, 0, 0, 15, 0, 104, 106, 114, 116, 121, 126, 128, 134, 136, 147, 151, 154, 172, 183, 1, 0, 1, 0] \ No newline at end of file diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseLexer.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseLexer.java deleted file mode 100644 index b7fe9696af..0000000000 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseLexer.java +++ /dev/null @@ -1,243 +0,0 @@ -// Generated from io/edurt/datacap/sql/parser/SqlBase.g4 by ANTLR 4.12.0 -package io.edurt.datacap.sql.parser; -import org.antlr.v4.runtime.Lexer; -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.Token; -import org.antlr.v4.runtime.TokenStream; -import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.atn.*; -import org.antlr.v4.runtime.dfa.DFA; -import org.antlr.v4.runtime.misc.*; - -@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue"}) -public class SqlBaseLexer extends Lexer { - static { RuntimeMetaData.checkVersion("4.12.0", RuntimeMetaData.VERSION); } - - protected static final DFA[] _decisionToDFA; - protected static final PredictionContextCache _sharedContextCache = - new PredictionContextCache(); - public static final int - T__0=1, SHOW=2, PATHS=3, TOPICS=4, CONSUMERS=5, DATABASES=6, TABLES=7, - SELECT=8, FROM=9, STRING=10, IDENTIFIER=11, BACKQUOTED_IDENTIFIER=12, - SIMPLE_COMMENT=13, BRACKETED_EMPTY_COMMENT=14, BRACKETED_COMMENT=15, WS=16; - public static String[] channelNames = { - "DEFAULT_TOKEN_CHANNEL", "HIDDEN" - }; - - public static String[] modeNames = { - "DEFAULT_MODE" - }; - - private static String[] makeRuleNames() { - return new String[] { - "T__0", "SHOW", "PATHS", "TOPICS", "CONSUMERS", "DATABASES", "TABLES", - "SELECT", "FROM", "DIGIT", "LETTER", "STRING", "IDENTIFIER", "BACKQUOTED_IDENTIFIER", - "SIMPLE_COMMENT", "BRACKETED_EMPTY_COMMENT", "BRACKETED_COMMENT", "WS" - }; - } - public static final String[] ruleNames = makeRuleNames(); - - private static String[] makeLiteralNames() { - return new String[] { - null, "'.'", null, null, "'TOPICS'", "'CONSUMERS'", null, null, null, - null, null, null, null, null, "'/**/'" - }; - } - private static final String[] _LITERAL_NAMES = makeLiteralNames(); - private static String[] makeSymbolicNames() { - return new String[] { - null, null, "SHOW", "PATHS", "TOPICS", "CONSUMERS", "DATABASES", "TABLES", - "SELECT", "FROM", "STRING", "IDENTIFIER", "BACKQUOTED_IDENTIFIER", "SIMPLE_COMMENT", - "BRACKETED_EMPTY_COMMENT", "BRACKETED_COMMENT", "WS" - }; - } - private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); - public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); - - /** - * @deprecated Use {@link #VOCABULARY} instead. - */ - @Deprecated - public static final String[] tokenNames; - static { - tokenNames = new String[_SYMBOLIC_NAMES.length]; - for (int i = 0; i < tokenNames.length; i++) { - tokenNames[i] = VOCABULARY.getLiteralName(i); - if (tokenNames[i] == null) { - tokenNames[i] = VOCABULARY.getSymbolicName(i); - } - - if (tokenNames[i] == null) { - tokenNames[i] = ""; - } - } - } - - @Override - @Deprecated - public String[] getTokenNames() { - return tokenNames; - } - - @Override - - public Vocabulary getVocabulary() { - return VOCABULARY; - } - - - public SqlBaseLexer(CharStream input) { - super(input); - _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); - } - - @Override - public String getGrammarFileName() { return "SqlBase.g4"; } - - @Override - public String[] getRuleNames() { return ruleNames; } - - @Override - public String getSerializedATN() { return _serializedATN; } - - @Override - public String[] getChannelNames() { return channelNames; } - - @Override - public String[] getModeNames() { return modeNames; } - - @Override - public ATN getATN() { return _ATN; } - - public static final String _serializedATN = - "\u0004\u0000\u0010\u00bb\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002"+ - "\u0001\u0007\u0001\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002"+ - "\u0004\u0007\u0004\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002"+ - "\u0007\u0007\u0007\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002"+ - "\u000b\u0007\u000b\u0002\f\u0007\f\u0002\r\u0007\r\u0002\u000e\u0007\u000e"+ - "\u0002\u000f\u0007\u000f\u0002\u0010\u0007\u0010\u0002\u0011\u0007\u0011"+ - "\u0001\u0000\u0001\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ - "\u0001\u0001\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002"+ - "\u0001\u0002\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ - "\u0001\u0003\u0001\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+ - "\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+ - "\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005"+ - "\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0006\u0001\u0006"+ - "\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0007"+ - "\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007"+ - "\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\t\u0001\t\u0001\n\u0001"+ - "\n\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0005\u000bi\b\u000b"+ - "\n\u000b\f\u000bl\t\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b"+ - "\u0001\u000b\u0005\u000bs\b\u000b\n\u000b\f\u000bv\t\u000b\u0001\u000b"+ - "\u0001\u000b\u0003\u000bz\b\u000b\u0001\f\u0001\f\u0001\f\u0004\f\u007f"+ - "\b\f\u000b\f\f\f\u0080\u0001\r\u0001\r\u0001\r\u0001\r\u0005\r\u0087\b"+ - "\r\n\r\f\r\u008a\t\r\u0001\r\u0001\r\u0001\u000e\u0001\u000e\u0001\u000e"+ - "\u0001\u000e\u0005\u000e\u0092\b\u000e\n\u000e\f\u000e\u0095\t\u000e\u0001"+ - "\u000e\u0003\u000e\u0098\b\u000e\u0001\u000e\u0003\u000e\u009b\b\u000e"+ - "\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f"+ - "\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0001\u0010"+ - "\u0001\u0010\u0001\u0010\u0005\u0010\u00ab\b\u0010\n\u0010\f\u0010\u00ae"+ - "\t\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001"+ - "\u0011\u0004\u0011\u00b6\b\u0011\u000b\u0011\f\u0011\u00b7\u0001\u0011"+ - "\u0001\u0011\u0001\u00ac\u0000\u0012\u0001\u0001\u0003\u0002\u0005\u0003"+ - "\u0007\u0004\t\u0005\u000b\u0006\r\u0007\u000f\b\u0011\t\u0013\u0000\u0015"+ - "\u0000\u0017\n\u0019\u000b\u001b\f\u001d\r\u001f\u000e!\u000f#\u0010\u0001"+ - "\u0000\u0018\u0002\u0000SSss\u0002\u0000HHhh\u0002\u0000OOoo\u0002\u0000"+ - "WWww\u0002\u0000PPpp\u0002\u0000AAaa\u0002\u0000TTtt\u0002\u0000DDdd\u0002"+ - "\u0000BBbb\u0002\u0000EEss\u0002\u0000LLll\u0002\u0000EEee\u0002\u0000"+ - "CCcc\u0002\u0000FFff\u0002\u0000RRrr\u0002\u0000MMmm\u0001\u000009\u0002"+ - "\u0000AZaz\u0002\u0000\'\'\\\\\u0002\u0000\"\"\\\\\u0001\u0000``\u0002"+ - "\u0000\n\n\r\r\u0001\u0000++\u0003\u0000\t\n\r\r \u00c8\u0000\u0001\u0001"+ - "\u0000\u0000\u0000\u0000\u0003\u0001\u0000\u0000\u0000\u0000\u0005\u0001"+ - "\u0000\u0000\u0000\u0000\u0007\u0001\u0000\u0000\u0000\u0000\t\u0001\u0000"+ - "\u0000\u0000\u0000\u000b\u0001\u0000\u0000\u0000\u0000\r\u0001\u0000\u0000"+ - "\u0000\u0000\u000f\u0001\u0000\u0000\u0000\u0000\u0011\u0001\u0000\u0000"+ - "\u0000\u0000\u0017\u0001\u0000\u0000\u0000\u0000\u0019\u0001\u0000\u0000"+ - "\u0000\u0000\u001b\u0001\u0000\u0000\u0000\u0000\u001d\u0001\u0000\u0000"+ - "\u0000\u0000\u001f\u0001\u0000\u0000\u0000\u0000!\u0001\u0000\u0000\u0000"+ - "\u0000#\u0001\u0000\u0000\u0000\u0001%\u0001\u0000\u0000\u0000\u0003\'"+ - "\u0001\u0000\u0000\u0000\u0005,\u0001\u0000\u0000\u0000\u00072\u0001\u0000"+ - "\u0000\u0000\t9\u0001\u0000\u0000\u0000\u000bC\u0001\u0000\u0000\u0000"+ - "\rM\u0001\u0000\u0000\u0000\u000fT\u0001\u0000\u0000\u0000\u0011[\u0001"+ - "\u0000\u0000\u0000\u0013`\u0001\u0000\u0000\u0000\u0015b\u0001\u0000\u0000"+ - "\u0000\u0017y\u0001\u0000\u0000\u0000\u0019~\u0001\u0000\u0000\u0000\u001b"+ - "\u0082\u0001\u0000\u0000\u0000\u001d\u008d\u0001\u0000\u0000\u0000\u001f"+ - "\u009e\u0001\u0000\u0000\u0000!\u00a5\u0001\u0000\u0000\u0000#\u00b5\u0001"+ - "\u0000\u0000\u0000%&\u0005.\u0000\u0000&\u0002\u0001\u0000\u0000\u0000"+ - "\'(\u0007\u0000\u0000\u0000()\u0007\u0001\u0000\u0000)*\u0007\u0002\u0000"+ - "\u0000*+\u0007\u0003\u0000\u0000+\u0004\u0001\u0000\u0000\u0000,-\u0007"+ - "\u0004\u0000\u0000-.\u0007\u0005\u0000\u0000./\u0007\u0006\u0000\u0000"+ - "/0\u0007\u0001\u0000\u000001\u0007\u0000\u0000\u00001\u0006\u0001\u0000"+ - "\u0000\u000023\u0005T\u0000\u000034\u0005O\u0000\u000045\u0005P\u0000"+ - "\u000056\u0005I\u0000\u000067\u0005C\u0000\u000078\u0005S\u0000\u0000"+ - "8\b\u0001\u0000\u0000\u00009:\u0005C\u0000\u0000:;\u0005O\u0000\u0000"+ - ";<\u0005N\u0000\u0000<=\u0005S\u0000\u0000=>\u0005U\u0000\u0000>?\u0005"+ - "M\u0000\u0000?@\u0005E\u0000\u0000@A\u0005R\u0000\u0000AB\u0005S\u0000"+ - "\u0000B\n\u0001\u0000\u0000\u0000CD\u0007\u0007\u0000\u0000DE\u0007\u0005"+ - "\u0000\u0000EF\u0007\u0006\u0000\u0000FG\u0007\u0005\u0000\u0000GH\u0007"+ - "\b\u0000\u0000HI\u0007\u0005\u0000\u0000IJ\u0007\u0000\u0000\u0000JK\u0007"+ - "\t\u0000\u0000KL\u0007\u0000\u0000\u0000L\f\u0001\u0000\u0000\u0000MN"+ - "\u0007\u0006\u0000\u0000NO\u0007\u0005\u0000\u0000OP\u0007\b\u0000\u0000"+ - "PQ\u0007\n\u0000\u0000QR\u0007\u000b\u0000\u0000RS\u0007\u0000\u0000\u0000"+ - "S\u000e\u0001\u0000\u0000\u0000TU\u0007\u0000\u0000\u0000UV\u0007\u000b"+ - "\u0000\u0000VW\u0007\n\u0000\u0000WX\u0007\u000b\u0000\u0000XY\u0007\f"+ - "\u0000\u0000YZ\u0007\u0006\u0000\u0000Z\u0010\u0001\u0000\u0000\u0000"+ - "[\\\u0007\r\u0000\u0000\\]\u0007\u000e\u0000\u0000]^\u0007\u0002\u0000"+ - "\u0000^_\u0007\u000f\u0000\u0000_\u0012\u0001\u0000\u0000\u0000`a\u0007"+ - "\u0010\u0000\u0000a\u0014\u0001\u0000\u0000\u0000bc\u0007\u0011\u0000"+ - "\u0000c\u0016\u0001\u0000\u0000\u0000dj\u0005\'\u0000\u0000ei\b\u0012"+ - "\u0000\u0000fg\u0005\\\u0000\u0000gi\t\u0000\u0000\u0000he\u0001\u0000"+ - "\u0000\u0000hf\u0001\u0000\u0000\u0000il\u0001\u0000\u0000\u0000jh\u0001"+ - "\u0000\u0000\u0000jk\u0001\u0000\u0000\u0000km\u0001\u0000\u0000\u0000"+ - "lj\u0001\u0000\u0000\u0000mz\u0005\'\u0000\u0000nt\u0005\"\u0000\u0000"+ - "os\b\u0013\u0000\u0000pq\u0005\\\u0000\u0000qs\t\u0000\u0000\u0000ro\u0001"+ - "\u0000\u0000\u0000rp\u0001\u0000\u0000\u0000sv\u0001\u0000\u0000\u0000"+ - "tr\u0001\u0000\u0000\u0000tu\u0001\u0000\u0000\u0000uw\u0001\u0000\u0000"+ - "\u0000vt\u0001\u0000\u0000\u0000wz\u0005\"\u0000\u0000xz\u0005*\u0000"+ - "\u0000yd\u0001\u0000\u0000\u0000yn\u0001\u0000\u0000\u0000yx\u0001\u0000"+ - "\u0000\u0000z\u0018\u0001\u0000\u0000\u0000{\u007f\u0003\u0015\n\u0000"+ - "|\u007f\u0003\u0013\t\u0000}\u007f\u0005_\u0000\u0000~{\u0001\u0000\u0000"+ - "\u0000~|\u0001\u0000\u0000\u0000~}\u0001\u0000\u0000\u0000\u007f\u0080"+ - "\u0001\u0000\u0000\u0000\u0080~\u0001\u0000\u0000\u0000\u0080\u0081\u0001"+ - "\u0000\u0000\u0000\u0081\u001a\u0001\u0000\u0000\u0000\u0082\u0088\u0005"+ - "`\u0000\u0000\u0083\u0087\b\u0014\u0000\u0000\u0084\u0085\u0005`\u0000"+ - "\u0000\u0085\u0087\u0005`\u0000\u0000\u0086\u0083\u0001\u0000\u0000\u0000"+ - "\u0086\u0084\u0001\u0000\u0000\u0000\u0087\u008a\u0001\u0000\u0000\u0000"+ - "\u0088\u0086\u0001\u0000\u0000\u0000\u0088\u0089\u0001\u0000\u0000\u0000"+ - "\u0089\u008b\u0001\u0000\u0000\u0000\u008a\u0088\u0001\u0000\u0000\u0000"+ - "\u008b\u008c\u0005`\u0000\u0000\u008c\u001c\u0001\u0000\u0000\u0000\u008d"+ - "\u008e\u0005-\u0000\u0000\u008e\u008f\u0005-\u0000\u0000\u008f\u0093\u0001"+ - "\u0000\u0000\u0000\u0090\u0092\b\u0015\u0000\u0000\u0091\u0090\u0001\u0000"+ - "\u0000\u0000\u0092\u0095\u0001\u0000\u0000\u0000\u0093\u0091\u0001\u0000"+ - "\u0000\u0000\u0093\u0094\u0001\u0000\u0000\u0000\u0094\u0097\u0001\u0000"+ - "\u0000\u0000\u0095\u0093\u0001\u0000\u0000\u0000\u0096\u0098\u0005\r\u0000"+ - "\u0000\u0097\u0096\u0001\u0000\u0000\u0000\u0097\u0098\u0001\u0000\u0000"+ - "\u0000\u0098\u009a\u0001\u0000\u0000\u0000\u0099\u009b\u0005\n\u0000\u0000"+ - "\u009a\u0099\u0001\u0000\u0000\u0000\u009a\u009b\u0001\u0000\u0000\u0000"+ - "\u009b\u009c\u0001\u0000\u0000\u0000\u009c\u009d\u0006\u000e\u0000\u0000"+ - "\u009d\u001e\u0001\u0000\u0000\u0000\u009e\u009f\u0005/\u0000\u0000\u009f"+ - "\u00a0\u0005*\u0000\u0000\u00a0\u00a1\u0005*\u0000\u0000\u00a1\u00a2\u0005"+ - "/\u0000\u0000\u00a2\u00a3\u0001\u0000\u0000\u0000\u00a3\u00a4\u0006\u000f"+ - "\u0000\u0000\u00a4 \u0001\u0000\u0000\u0000\u00a5\u00a6\u0005/\u0000\u0000"+ - "\u00a6\u00a7\u0005*\u0000\u0000\u00a7\u00a8\u0001\u0000\u0000\u0000\u00a8"+ - "\u00ac\b\u0016\u0000\u0000\u00a9\u00ab\t\u0000\u0000\u0000\u00aa\u00a9"+ - "\u0001\u0000\u0000\u0000\u00ab\u00ae\u0001\u0000\u0000\u0000\u00ac\u00ad"+ - "\u0001\u0000\u0000\u0000\u00ac\u00aa\u0001\u0000\u0000\u0000\u00ad\u00af"+ - "\u0001\u0000\u0000\u0000\u00ae\u00ac\u0001\u0000\u0000\u0000\u00af\u00b0"+ - "\u0005*\u0000\u0000\u00b0\u00b1\u0005/\u0000\u0000\u00b1\u00b2\u0001\u0000"+ - "\u0000\u0000\u00b2\u00b3\u0006\u0010\u0000\u0000\u00b3\"\u0001\u0000\u0000"+ - "\u0000\u00b4\u00b6\u0007\u0017\u0000\u0000\u00b5\u00b4\u0001\u0000\u0000"+ - "\u0000\u00b6\u00b7\u0001\u0000\u0000\u0000\u00b7\u00b5\u0001\u0000\u0000"+ - "\u0000\u00b7\u00b8\u0001\u0000\u0000\u0000\u00b8\u00b9\u0001\u0000\u0000"+ - "\u0000\u00b9\u00ba\u0006\u0011\u0000\u0000\u00ba$\u0001\u0000\u0000\u0000"+ - "\u000f\u0000hjrty~\u0080\u0086\u0088\u0093\u0097\u009a\u00ac\u00b7\u0001"+ - "\u0000\u0001\u0000"; - public static final ATN _ATN = - new ATNDeserializer().deserialize(_serializedATN.toCharArray()); - static { - _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; - for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { - _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); - } - } -} \ No newline at end of file diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseListener.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseListener.java deleted file mode 100644 index ec47bb84eb..0000000000 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseListener.java +++ /dev/null @@ -1,130 +0,0 @@ -// Generated from io/edurt/datacap/sql/parser/SqlBase.g4 by ANTLR 4.12.0 -package io.edurt.datacap.sql.parser; -import org.antlr.v4.runtime.tree.ParseTreeListener; - -/** - * This interface defines a complete listener for a parse tree produced by - * {@link SqlBaseParser}. - */ -public interface SqlBaseListener extends ParseTreeListener { - /** - * Enter a parse tree produced by {@link SqlBaseParser#singleStatement}. - * @param ctx the parse tree - */ - void enterSingleStatement(SqlBaseParser.SingleStatementContext ctx); - /** - * Exit a parse tree produced by {@link SqlBaseParser#singleStatement}. - * @param ctx the parse tree - */ - void exitSingleStatement(SqlBaseParser.SingleStatementContext ctx); - /** - * Enter a parse tree produced by {@link SqlBaseParser#statement}. - * @param ctx the parse tree - */ - void enterStatement(SqlBaseParser.StatementContext ctx); - /** - * Exit a parse tree produced by {@link SqlBaseParser#statement}. - * @param ctx the parse tree - */ - void exitStatement(SqlBaseParser.StatementContext ctx); - /** - * Enter a parse tree produced by {@link SqlBaseParser#kafkaQueryTopicStatement}. - * @param ctx the parse tree - */ - void enterKafkaQueryTopicStatement(SqlBaseParser.KafkaQueryTopicStatementContext ctx); - /** - * Exit a parse tree produced by {@link SqlBaseParser#kafkaQueryTopicStatement}. - * @param ctx the parse tree - */ - void exitKafkaQueryTopicStatement(SqlBaseParser.KafkaQueryTopicStatementContext ctx); - /** - * Enter a parse tree produced by {@link SqlBaseParser#kafkaQueryConsumerStatement}. - * @param ctx the parse tree - */ - void enterKafkaQueryConsumerStatement(SqlBaseParser.KafkaQueryConsumerStatementContext ctx); - /** - * Exit a parse tree produced by {@link SqlBaseParser#kafkaQueryConsumerStatement}. - * @param ctx the parse tree - */ - void exitKafkaQueryConsumerStatement(SqlBaseParser.KafkaQueryConsumerStatementContext ctx); - /** - * Enter a parse tree produced by {@link SqlBaseParser#kafkaQueryStatement}. - * @param ctx the parse tree - */ - void enterKafkaQueryStatement(SqlBaseParser.KafkaQueryStatementContext ctx); - /** - * Exit a parse tree produced by {@link SqlBaseParser#kafkaQueryStatement}. - * @param ctx the parse tree - */ - void exitKafkaQueryStatement(SqlBaseParser.KafkaQueryStatementContext ctx); - /** - * Enter a parse tree produced by {@link SqlBaseParser#kafkaStatement}. - * @param ctx the parse tree - */ - void enterKafkaStatement(SqlBaseParser.KafkaStatementContext ctx); - /** - * Exit a parse tree produced by {@link SqlBaseParser#kafkaStatement}. - * @param ctx the parse tree - */ - void exitKafkaStatement(SqlBaseParser.KafkaStatementContext ctx); - /** - * Enter a parse tree produced by {@link SqlBaseParser#childPathStatement}. - * @param ctx the parse tree - */ - void enterChildPathStatement(SqlBaseParser.ChildPathStatementContext ctx); - /** - * Exit a parse tree produced by {@link SqlBaseParser#childPathStatement}. - * @param ctx the parse tree - */ - void exitChildPathStatement(SqlBaseParser.ChildPathStatementContext ctx); - /** - * Enter a parse tree produced by {@link SqlBaseParser#columnStatement}. - * @param ctx the parse tree - */ - void enterColumnStatement(SqlBaseParser.ColumnStatementContext ctx); - /** - * Exit a parse tree produced by {@link SqlBaseParser#columnStatement}. - * @param ctx the parse tree - */ - void exitColumnStatement(SqlBaseParser.ColumnStatementContext ctx); - /** - * Enter a parse tree produced by {@link SqlBaseParser#fromClause}. - * @param ctx the parse tree - */ - void enterFromClause(SqlBaseParser.FromClauseContext ctx); - /** - * Exit a parse tree produced by {@link SqlBaseParser#fromClause}. - * @param ctx the parse tree - */ - void exitFromClause(SqlBaseParser.FromClauseContext ctx); - /** - * Enter a parse tree produced by {@link SqlBaseParser#tableName}. - * @param ctx the parse tree - */ - void enterTableName(SqlBaseParser.TableNameContext ctx); - /** - * Exit a parse tree produced by {@link SqlBaseParser#tableName}. - * @param ctx the parse tree - */ - void exitTableName(SqlBaseParser.TableNameContext ctx); - /** - * Enter a parse tree produced by {@link SqlBaseParser#identifier}. - * @param ctx the parse tree - */ - void enterIdentifier(SqlBaseParser.IdentifierContext ctx); - /** - * Exit a parse tree produced by {@link SqlBaseParser#identifier}. - * @param ctx the parse tree - */ - void exitIdentifier(SqlBaseParser.IdentifierContext ctx); - /** - * Enter a parse tree produced by {@link SqlBaseParser#quotedIdentifier}. - * @param ctx the parse tree - */ - void enterQuotedIdentifier(SqlBaseParser.QuotedIdentifierContext ctx); - /** - * Exit a parse tree produced by {@link SqlBaseParser#quotedIdentifier}. - * @param ctx the parse tree - */ - void exitQuotedIdentifier(SqlBaseParser.QuotedIdentifierContext ctx); -} \ No newline at end of file diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseParser.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseParser.java deleted file mode 100644 index ed18dea1e4..0000000000 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseParser.java +++ /dev/null @@ -1,911 +0,0 @@ -// Generated from io/edurt/datacap/sql/parser/SqlBase.g4 by ANTLR 4.12.0 -package io.edurt.datacap.sql.parser; -import org.antlr.v4.runtime.atn.*; -import org.antlr.v4.runtime.dfa.DFA; -import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.misc.*; -import org.antlr.v4.runtime.tree.*; -import java.util.List; -import java.util.Iterator; -import java.util.ArrayList; - -@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue"}) -public class SqlBaseParser extends Parser { - static { RuntimeMetaData.checkVersion("4.12.0", RuntimeMetaData.VERSION); } - - protected static final DFA[] _decisionToDFA; - protected static final PredictionContextCache _sharedContextCache = - new PredictionContextCache(); - public static final int - T__0=1, SHOW=2, PATHS=3, TOPICS=4, CONSUMERS=5, DATABASES=6, TABLES=7, - SELECT=8, FROM=9, STRING=10, IDENTIFIER=11, BACKQUOTED_IDENTIFIER=12, - SIMPLE_COMMENT=13, BRACKETED_EMPTY_COMMENT=14, BRACKETED_COMMENT=15, WS=16; - public static final int - RULE_singleStatement = 0, RULE_statement = 1, RULE_kafkaQueryTopicStatement = 2, - RULE_kafkaQueryConsumerStatement = 3, RULE_kafkaQueryStatement = 4, RULE_kafkaStatement = 5, - RULE_childPathStatement = 6, RULE_columnStatement = 7, RULE_fromClause = 8, - RULE_tableName = 9, RULE_identifier = 10, RULE_quotedIdentifier = 11; - private static String[] makeRuleNames() { - return new String[] { - "singleStatement", "statement", "kafkaQueryTopicStatement", "kafkaQueryConsumerStatement", - "kafkaQueryStatement", "kafkaStatement", "childPathStatement", "columnStatement", - "fromClause", "tableName", "identifier", "quotedIdentifier" - }; - } - public static final String[] ruleNames = makeRuleNames(); - - private static String[] makeLiteralNames() { - return new String[] { - null, "'.'", null, null, "'TOPICS'", "'CONSUMERS'", null, null, null, - null, null, null, null, null, "'/**/'" - }; - } - private static final String[] _LITERAL_NAMES = makeLiteralNames(); - private static String[] makeSymbolicNames() { - return new String[] { - null, null, "SHOW", "PATHS", "TOPICS", "CONSUMERS", "DATABASES", "TABLES", - "SELECT", "FROM", "STRING", "IDENTIFIER", "BACKQUOTED_IDENTIFIER", "SIMPLE_COMMENT", - "BRACKETED_EMPTY_COMMENT", "BRACKETED_COMMENT", "WS" - }; - } - private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); - public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); - - /** - * @deprecated Use {@link #VOCABULARY} instead. - */ - @Deprecated - public static final String[] tokenNames; - static { - tokenNames = new String[_SYMBOLIC_NAMES.length]; - for (int i = 0; i < tokenNames.length; i++) { - tokenNames[i] = VOCABULARY.getLiteralName(i); - if (tokenNames[i] == null) { - tokenNames[i] = VOCABULARY.getSymbolicName(i); - } - - if (tokenNames[i] == null) { - tokenNames[i] = ""; - } - } - } - - @Override - @Deprecated - public String[] getTokenNames() { - return tokenNames; - } - - @Override - - public Vocabulary getVocabulary() { - return VOCABULARY; - } - - @Override - public String getGrammarFileName() { return "SqlBase.g4"; } - - @Override - public String[] getRuleNames() { return ruleNames; } - - @Override - public String getSerializedATN() { return _serializedATN; } - - @Override - public ATN getATN() { return _ATN; } - - public SqlBaseParser(TokenStream input) { - super(input); - _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); - } - - @SuppressWarnings("CheckReturnValue") - public static class SingleStatementContext extends ParserRuleContext { - public List statement() { - return getRuleContexts(StatementContext.class); - } - public StatementContext statement(int i) { - return getRuleContext(StatementContext.class,i); - } - public SingleStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_singleStatement; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).enterSingleStatement(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).exitSingleStatement(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof SqlBaseVisitor ) return ((SqlBaseVisitor)visitor).visitSingleStatement(this); - else return visitor.visitChildren(this); - } - } - - public final SingleStatementContext singleStatement() throws RecognitionException { - SingleStatementContext _localctx = new SingleStatementContext(_ctx, getState()); - enterRule(_localctx, 0, RULE_singleStatement); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(27); - _errHandler.sync(this); - _la = _input.LA(1); - while (_la==SHOW || _la==SELECT) { - { - { - setState(24); - statement(); - } - } - setState(29); - _errHandler.sync(this); - _la = _input.LA(1); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class StatementContext extends ParserRuleContext { - public TerminalNode SHOW() { return getToken(SqlBaseParser.SHOW, 0); } - public ChildPathStatementContext childPathStatement() { - return getRuleContext(ChildPathStatementContext.class,0); - } - public TerminalNode SELECT() { return getToken(SqlBaseParser.SELECT, 0); } - public ColumnStatementContext columnStatement() { - return getRuleContext(ColumnStatementContext.class,0); - } - public FromClauseContext fromClause() { - return getRuleContext(FromClauseContext.class,0); - } - public KafkaStatementContext kafkaStatement() { - return getRuleContext(KafkaStatementContext.class,0); - } - public StatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_statement; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).enterStatement(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).exitStatement(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof SqlBaseVisitor ) return ((SqlBaseVisitor)visitor).visitStatement(this); - else return visitor.visitChildren(this); - } - } - - public final StatementContext statement() throws RecognitionException { - StatementContext _localctx = new StatementContext(_ctx, getState()); - enterRule(_localctx, 2, RULE_statement); - try { - setState(37); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,1,_ctx) ) { - case 1: - enterOuterAlt(_localctx, 1); - { - setState(30); - match(SHOW); - setState(31); - childPathStatement(); - } - break; - case 2: - enterOuterAlt(_localctx, 2); - { - setState(32); - match(SELECT); - setState(33); - columnStatement(); - setState(34); - fromClause(); - } - break; - case 3: - enterOuterAlt(_localctx, 3); - { - setState(36); - kafkaStatement(); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class KafkaQueryTopicStatementContext extends ParserRuleContext { - public TerminalNode SHOW() { return getToken(SqlBaseParser.SHOW, 0); } - public TerminalNode TOPICS() { return getToken(SqlBaseParser.TOPICS, 0); } - public TerminalNode DATABASES() { return getToken(SqlBaseParser.DATABASES, 0); } - public KafkaQueryTopicStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_kafkaQueryTopicStatement; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).enterKafkaQueryTopicStatement(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).exitKafkaQueryTopicStatement(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof SqlBaseVisitor ) return ((SqlBaseVisitor)visitor).visitKafkaQueryTopicStatement(this); - else return visitor.visitChildren(this); - } - } - - public final KafkaQueryTopicStatementContext kafkaQueryTopicStatement() throws RecognitionException { - KafkaQueryTopicStatementContext _localctx = new KafkaQueryTopicStatementContext(_ctx, getState()); - enterRule(_localctx, 4, RULE_kafkaQueryTopicStatement); - try { - setState(43); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,2,_ctx) ) { - case 1: - enterOuterAlt(_localctx, 1); - { - setState(39); - match(SHOW); - setState(40); - match(TOPICS); - } - break; - case 2: - enterOuterAlt(_localctx, 2); - { - setState(41); - match(SHOW); - setState(42); - match(DATABASES); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class KafkaQueryConsumerStatementContext extends ParserRuleContext { - public TerminalNode SHOW() { return getToken(SqlBaseParser.SHOW, 0); } - public TerminalNode CONSUMERS() { return getToken(SqlBaseParser.CONSUMERS, 0); } - public FromClauseContext fromClause() { - return getRuleContext(FromClauseContext.class,0); - } - public TerminalNode TABLES() { return getToken(SqlBaseParser.TABLES, 0); } - public KafkaQueryConsumerStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_kafkaQueryConsumerStatement; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).enterKafkaQueryConsumerStatement(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).exitKafkaQueryConsumerStatement(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof SqlBaseVisitor ) return ((SqlBaseVisitor)visitor).visitKafkaQueryConsumerStatement(this); - else return visitor.visitChildren(this); - } - } - - public final KafkaQueryConsumerStatementContext kafkaQueryConsumerStatement() throws RecognitionException { - KafkaQueryConsumerStatementContext _localctx = new KafkaQueryConsumerStatementContext(_ctx, getState()); - enterRule(_localctx, 6, RULE_kafkaQueryConsumerStatement); - try { - setState(55); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,3,_ctx) ) { - case 1: - enterOuterAlt(_localctx, 1); - { - setState(45); - match(SHOW); - setState(46); - match(CONSUMERS); - } - break; - case 2: - enterOuterAlt(_localctx, 2); - { - setState(47); - match(SHOW); - setState(48); - match(CONSUMERS); - setState(49); - fromClause(); - } - break; - case 3: - enterOuterAlt(_localctx, 3); - { - setState(50); - match(SHOW); - setState(51); - match(TABLES); - } - break; - case 4: - enterOuterAlt(_localctx, 4); - { - setState(52); - match(SHOW); - setState(53); - match(TABLES); - setState(54); - fromClause(); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class KafkaQueryStatementContext extends ParserRuleContext { - public KafkaQueryTopicStatementContext kafkaQueryTopicStatement() { - return getRuleContext(KafkaQueryTopicStatementContext.class,0); - } - public KafkaQueryConsumerStatementContext kafkaQueryConsumerStatement() { - return getRuleContext(KafkaQueryConsumerStatementContext.class,0); - } - public KafkaQueryStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_kafkaQueryStatement; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).enterKafkaQueryStatement(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).exitKafkaQueryStatement(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof SqlBaseVisitor ) return ((SqlBaseVisitor)visitor).visitKafkaQueryStatement(this); - else return visitor.visitChildren(this); - } - } - - public final KafkaQueryStatementContext kafkaQueryStatement() throws RecognitionException { - KafkaQueryStatementContext _localctx = new KafkaQueryStatementContext(_ctx, getState()); - enterRule(_localctx, 8, RULE_kafkaQueryStatement); - try { - setState(59); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,4,_ctx) ) { - case 1: - enterOuterAlt(_localctx, 1); - { - setState(57); - kafkaQueryTopicStatement(); - } - break; - case 2: - enterOuterAlt(_localctx, 2); - { - setState(58); - kafkaQueryConsumerStatement(); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class KafkaStatementContext extends ParserRuleContext { - public KafkaQueryStatementContext kafkaQueryStatement() { - return getRuleContext(KafkaQueryStatementContext.class,0); - } - public KafkaStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_kafkaStatement; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).enterKafkaStatement(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).exitKafkaStatement(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof SqlBaseVisitor ) return ((SqlBaseVisitor)visitor).visitKafkaStatement(this); - else return visitor.visitChildren(this); - } - } - - public final KafkaStatementContext kafkaStatement() throws RecognitionException { - KafkaStatementContext _localctx = new KafkaStatementContext(_ctx, getState()); - enterRule(_localctx, 10, RULE_kafkaStatement); - try { - enterOuterAlt(_localctx, 1); - { - setState(61); - kafkaQueryStatement(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ChildPathStatementContext extends ParserRuleContext { - public TerminalNode PATHS() { return getToken(SqlBaseParser.PATHS, 0); } - public FromClauseContext fromClause() { - return getRuleContext(FromClauseContext.class,0); - } - public ChildPathStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_childPathStatement; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).enterChildPathStatement(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).exitChildPathStatement(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof SqlBaseVisitor ) return ((SqlBaseVisitor)visitor).visitChildPathStatement(this); - else return visitor.visitChildren(this); - } - } - - public final ChildPathStatementContext childPathStatement() throws RecognitionException { - ChildPathStatementContext _localctx = new ChildPathStatementContext(_ctx, getState()); - enterRule(_localctx, 12, RULE_childPathStatement); - try { - setState(66); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,5,_ctx) ) { - case 1: - enterOuterAlt(_localctx, 1); - { - setState(63); - match(PATHS); - } - break; - case 2: - enterOuterAlt(_localctx, 2); - { - setState(64); - match(PATHS); - setState(65); - fromClause(); - } - break; - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ColumnStatementContext extends ParserRuleContext { - public IdentifierContext identifier() { - return getRuleContext(IdentifierContext.class,0); - } - public ColumnStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_columnStatement; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).enterColumnStatement(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).exitColumnStatement(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof SqlBaseVisitor ) return ((SqlBaseVisitor)visitor).visitColumnStatement(this); - else return visitor.visitChildren(this); - } - } - - public final ColumnStatementContext columnStatement() throws RecognitionException { - ColumnStatementContext _localctx = new ColumnStatementContext(_ctx, getState()); - enterRule(_localctx, 14, RULE_columnStatement); - try { - enterOuterAlt(_localctx, 1); - { - setState(68); - identifier(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class FromClauseContext extends ParserRuleContext { - public TerminalNode FROM() { return getToken(SqlBaseParser.FROM, 0); } - public TableNameContext tableName() { - return getRuleContext(TableNameContext.class,0); - } - public FromClauseContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_fromClause; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).enterFromClause(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).exitFromClause(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof SqlBaseVisitor ) return ((SqlBaseVisitor)visitor).visitFromClause(this); - else return visitor.visitChildren(this); - } - } - - public final FromClauseContext fromClause() throws RecognitionException { - FromClauseContext _localctx = new FromClauseContext(_ctx, getState()); - enterRule(_localctx, 16, RULE_fromClause); - try { - enterOuterAlt(_localctx, 1); - { - setState(70); - match(FROM); - setState(71); - tableName(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class TableNameContext extends ParserRuleContext { - public List identifier() { - return getRuleContexts(IdentifierContext.class); - } - public IdentifierContext identifier(int i) { - return getRuleContext(IdentifierContext.class,i); - } - public TableNameContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_tableName; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).enterTableName(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).exitTableName(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof SqlBaseVisitor ) return ((SqlBaseVisitor)visitor).visitTableName(this); - else return visitor.visitChildren(this); - } - } - - public final TableNameContext tableName() throws RecognitionException { - TableNameContext _localctx = new TableNameContext(_ctx, getState()); - enterRule(_localctx, 18, RULE_tableName); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(73); - identifier(); - setState(78); - _errHandler.sync(this); - _la = _input.LA(1); - while (_la==T__0) { - { - { - setState(74); - match(T__0); - setState(75); - identifier(); - } - } - setState(80); - _errHandler.sync(this); - _la = _input.LA(1); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class IdentifierContext extends ParserRuleContext { - public List IDENTIFIER() { return getTokens(SqlBaseParser.IDENTIFIER); } - public TerminalNode IDENTIFIER(int i) { - return getToken(SqlBaseParser.IDENTIFIER, i); - } - public List STRING() { return getTokens(SqlBaseParser.STRING); } - public TerminalNode STRING(int i) { - return getToken(SqlBaseParser.STRING, i); - } - public List quotedIdentifier() { - return getRuleContexts(QuotedIdentifierContext.class); - } - public QuotedIdentifierContext quotedIdentifier(int i) { - return getRuleContext(QuotedIdentifierContext.class,i); - } - public IdentifierContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_identifier; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).enterIdentifier(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).exitIdentifier(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof SqlBaseVisitor ) return ((SqlBaseVisitor)visitor).visitIdentifier(this); - else return visitor.visitChildren(this); - } - } - - public final IdentifierContext identifier() throws RecognitionException { - IdentifierContext _localctx = new IdentifierContext(_ctx, getState()); - enterRule(_localctx, 20, RULE_identifier); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(86); - _errHandler.sync(this); - _la = _input.LA(1); - while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 7168L) != 0)) { - { - setState(84); - _errHandler.sync(this); - switch (_input.LA(1)) { - case IDENTIFIER: - { - setState(81); - match(IDENTIFIER); - } - break; - case STRING: - { - setState(82); - match(STRING); - } - break; - case BACKQUOTED_IDENTIFIER: - { - setState(83); - quotedIdentifier(); - } - break; - default: - throw new NoViableAltException(this); - } - } - setState(88); - _errHandler.sync(this); - _la = _input.LA(1); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class QuotedIdentifierContext extends ParserRuleContext { - public TerminalNode BACKQUOTED_IDENTIFIER() { return getToken(SqlBaseParser.BACKQUOTED_IDENTIFIER, 0); } - public QuotedIdentifierContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_quotedIdentifier; } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).enterQuotedIdentifier(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof SqlBaseListener ) ((SqlBaseListener)listener).exitQuotedIdentifier(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof SqlBaseVisitor ) return ((SqlBaseVisitor)visitor).visitQuotedIdentifier(this); - else return visitor.visitChildren(this); - } - } - - public final QuotedIdentifierContext quotedIdentifier() throws RecognitionException { - QuotedIdentifierContext _localctx = new QuotedIdentifierContext(_ctx, getState()); - enterRule(_localctx, 22, RULE_quotedIdentifier); - try { - enterOuterAlt(_localctx, 1); - { - setState(89); - match(BACKQUOTED_IDENTIFIER); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static final String _serializedATN = - "\u0004\u0001\u0010\\\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0002"+ - "\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004\u0007\u0004\u0002"+ - "\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007\u0007\u0007\u0002"+ - "\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b\u0007\u000b\u0001"+ - "\u0000\u0005\u0000\u001a\b\u0000\n\u0000\f\u0000\u001d\t\u0000\u0001\u0001"+ - "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ - "\u0003\u0001&\b\u0001\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002"+ - "\u0003\u0002,\b\u0002\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ - "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003"+ - "\u0003\u00038\b\u0003\u0001\u0004\u0001\u0004\u0003\u0004<\b\u0004\u0001"+ - "\u0005\u0001\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0003\u0006C\b"+ - "\u0006\u0001\u0007\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001\t\u0001\t"+ - "\u0001\t\u0005\tM\b\t\n\t\f\tP\t\t\u0001\n\u0001\n\u0001\n\u0005\nU\b"+ - "\n\n\n\f\nX\t\n\u0001\u000b\u0001\u000b\u0001\u000b\u0000\u0000\f\u0000"+ - "\u0002\u0004\u0006\b\n\f\u000e\u0010\u0012\u0014\u0016\u0000\u0000\\\u0000"+ - "\u001b\u0001\u0000\u0000\u0000\u0002%\u0001\u0000\u0000\u0000\u0004+\u0001"+ - "\u0000\u0000\u0000\u00067\u0001\u0000\u0000\u0000\b;\u0001\u0000\u0000"+ - "\u0000\n=\u0001\u0000\u0000\u0000\fB\u0001\u0000\u0000\u0000\u000eD\u0001"+ - "\u0000\u0000\u0000\u0010F\u0001\u0000\u0000\u0000\u0012I\u0001\u0000\u0000"+ - "\u0000\u0014V\u0001\u0000\u0000\u0000\u0016Y\u0001\u0000\u0000\u0000\u0018"+ - "\u001a\u0003\u0002\u0001\u0000\u0019\u0018\u0001\u0000\u0000\u0000\u001a"+ - "\u001d\u0001\u0000\u0000\u0000\u001b\u0019\u0001\u0000\u0000\u0000\u001b"+ - "\u001c\u0001\u0000\u0000\u0000\u001c\u0001\u0001\u0000\u0000\u0000\u001d"+ - "\u001b\u0001\u0000\u0000\u0000\u001e\u001f\u0005\u0002\u0000\u0000\u001f"+ - "&\u0003\f\u0006\u0000 !\u0005\b\u0000\u0000!\"\u0003\u000e\u0007\u0000"+ - "\"#\u0003\u0010\b\u0000#&\u0001\u0000\u0000\u0000$&\u0003\n\u0005\u0000"+ - "%\u001e\u0001\u0000\u0000\u0000% \u0001\u0000\u0000\u0000%$\u0001\u0000"+ - "\u0000\u0000&\u0003\u0001\u0000\u0000\u0000\'(\u0005\u0002\u0000\u0000"+ - "(,\u0005\u0004\u0000\u0000)*\u0005\u0002\u0000\u0000*,\u0005\u0006\u0000"+ - "\u0000+\'\u0001\u0000\u0000\u0000+)\u0001\u0000\u0000\u0000,\u0005\u0001"+ - "\u0000\u0000\u0000-.\u0005\u0002\u0000\u0000.8\u0005\u0005\u0000\u0000"+ - "/0\u0005\u0002\u0000\u000001\u0005\u0005\u0000\u000018\u0003\u0010\b\u0000"+ - "23\u0005\u0002\u0000\u000038\u0005\u0007\u0000\u000045\u0005\u0002\u0000"+ - "\u000056\u0005\u0007\u0000\u000068\u0003\u0010\b\u00007-\u0001\u0000\u0000"+ - "\u00007/\u0001\u0000\u0000\u000072\u0001\u0000\u0000\u000074\u0001\u0000"+ - "\u0000\u00008\u0007\u0001\u0000\u0000\u00009<\u0003\u0004\u0002\u0000"+ - ":<\u0003\u0006\u0003\u0000;9\u0001\u0000\u0000\u0000;:\u0001\u0000\u0000"+ - "\u0000<\t\u0001\u0000\u0000\u0000=>\u0003\b\u0004\u0000>\u000b\u0001\u0000"+ - "\u0000\u0000?C\u0005\u0003\u0000\u0000@A\u0005\u0003\u0000\u0000AC\u0003"+ - "\u0010\b\u0000B?\u0001\u0000\u0000\u0000B@\u0001\u0000\u0000\u0000C\r"+ - "\u0001\u0000\u0000\u0000DE\u0003\u0014\n\u0000E\u000f\u0001\u0000\u0000"+ - "\u0000FG\u0005\t\u0000\u0000GH\u0003\u0012\t\u0000H\u0011\u0001\u0000"+ - "\u0000\u0000IN\u0003\u0014\n\u0000JK\u0005\u0001\u0000\u0000KM\u0003\u0014"+ - "\n\u0000LJ\u0001\u0000\u0000\u0000MP\u0001\u0000\u0000\u0000NL\u0001\u0000"+ - "\u0000\u0000NO\u0001\u0000\u0000\u0000O\u0013\u0001\u0000\u0000\u0000"+ - "PN\u0001\u0000\u0000\u0000QU\u0005\u000b\u0000\u0000RU\u0005\n\u0000\u0000"+ - "SU\u0003\u0016\u000b\u0000TQ\u0001\u0000\u0000\u0000TR\u0001\u0000\u0000"+ - "\u0000TS\u0001\u0000\u0000\u0000UX\u0001\u0000\u0000\u0000VT\u0001\u0000"+ - "\u0000\u0000VW\u0001\u0000\u0000\u0000W\u0015\u0001\u0000\u0000\u0000"+ - "XV\u0001\u0000\u0000\u0000YZ\u0005\f\u0000\u0000Z\u0017\u0001\u0000\u0000"+ - "\u0000\t\u001b%+7;BNTV"; - public static final ATN _ATN = - new ATNDeserializer().deserialize(_serializedATN.toCharArray()); - static { - _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; - for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { - _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); - } - } -} \ No newline at end of file diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseVisitor.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseVisitor.java deleted file mode 100644 index af88b64f76..0000000000 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/parser/SqlBaseVisitor.java +++ /dev/null @@ -1,85 +0,0 @@ -// Generated from io/edurt/datacap/sql/parser/SqlBase.g4 by ANTLR 4.12.0 -package io.edurt.datacap.sql.parser; -import org.antlr.v4.runtime.tree.ParseTreeVisitor; - -/** - * This interface defines a complete generic visitor for a parse tree produced - * by {@link SqlBaseParser}. - * - * @param The return type of the visit operation. Use {@link Void} for - * operations with no return type. - */ -public interface SqlBaseVisitor extends ParseTreeVisitor { - /** - * Visit a parse tree produced by {@link SqlBaseParser#singleStatement}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitSingleStatement(SqlBaseParser.SingleStatementContext ctx); - /** - * Visit a parse tree produced by {@link SqlBaseParser#statement}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitStatement(SqlBaseParser.StatementContext ctx); - /** - * Visit a parse tree produced by {@link SqlBaseParser#kafkaQueryTopicStatement}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitKafkaQueryTopicStatement(SqlBaseParser.KafkaQueryTopicStatementContext ctx); - /** - * Visit a parse tree produced by {@link SqlBaseParser#kafkaQueryConsumerStatement}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitKafkaQueryConsumerStatement(SqlBaseParser.KafkaQueryConsumerStatementContext ctx); - /** - * Visit a parse tree produced by {@link SqlBaseParser#kafkaQueryStatement}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitKafkaQueryStatement(SqlBaseParser.KafkaQueryStatementContext ctx); - /** - * Visit a parse tree produced by {@link SqlBaseParser#kafkaStatement}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitKafkaStatement(SqlBaseParser.KafkaStatementContext ctx); - /** - * Visit a parse tree produced by {@link SqlBaseParser#childPathStatement}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitChildPathStatement(SqlBaseParser.ChildPathStatementContext ctx); - /** - * Visit a parse tree produced by {@link SqlBaseParser#columnStatement}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitColumnStatement(SqlBaseParser.ColumnStatementContext ctx); - /** - * Visit a parse tree produced by {@link SqlBaseParser#fromClause}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitFromClause(SqlBaseParser.FromClauseContext ctx); - /** - * Visit a parse tree produced by {@link SqlBaseParser#tableName}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitTableName(SqlBaseParser.TableNameContext ctx); - /** - * Visit a parse tree produced by {@link SqlBaseParser#identifier}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitIdentifier(SqlBaseParser.IdentifierContext ctx); - /** - * Visit a parse tree produced by {@link SqlBaseParser#quotedIdentifier}. - * @param ctx the parse tree - * @return the visitor result - */ - T visitQuotedIdentifier(SqlBaseParser.QuotedIdentifierContext ctx); -} \ No newline at end of file diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/SQLStatement.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/SQLStatement.java new file mode 100644 index 0000000000..60eeb8c1a2 --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/SQLStatement.java @@ -0,0 +1,21 @@ +package io.edurt.datacap.sql.statement; + +public abstract class SQLStatement +{ + private final StatementType type; + + public SQLStatement(StatementType type) + { + this.type = type; + } + + public StatementType getType() + { + return type; + } + + public enum StatementType + { + SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, USE + } +} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/SelectStatement.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/SelectStatement.java new file mode 100644 index 0000000000..a1225fbac3 --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/SelectStatement.java @@ -0,0 +1,30 @@ +package io.edurt.datacap.sql.statement; + +import io.edurt.datacap.sql.node.Expression; +import io.edurt.datacap.sql.node.clause.LimitClause; +import io.edurt.datacap.sql.node.element.OrderByElement; +import io.edurt.datacap.sql.node.element.SelectElement; +import io.edurt.datacap.sql.node.element.TableElement; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class SelectStatement + extends SQLStatement +{ + private List selectElements; + private List fromSources; + private Expression whereClause; + private List groupByElements; + private Expression havingClause; + private List orderByElements; + private LimitClause limitClause; + + public SelectStatement() + { + super(StatementType.SELECT); + } +} diff --git a/core/datacap-parser/src/test/java/io/edurt/datacap/sql/KafkaParserTest.java b/core/datacap-parser/src/test/java/io/edurt/datacap/sql/KafkaParserTest.java deleted file mode 100644 index 7f2cfadff5..0000000000 --- a/core/datacap-parser/src/test/java/io/edurt/datacap/sql/KafkaParserTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.edurt.datacap.sql; - -import org.junit.Assert; -import org.junit.Test; - -public class KafkaParserTest -{ - private String table = "aa"; - - @Test - public void showTopic() - { - SqlBaseFormatter formatter = new SqlBaseFormatter("show topics"); - Assert.assertTrue(formatter.getParseResult().isSuccessful()); - } - - @Test - public void showConsumers() - { - SqlBaseFormatter formatter = new SqlBaseFormatter("show Consumers"); - Assert.assertTrue(formatter.getParseResult().isSuccessful()); - - formatter = new SqlBaseFormatter("show Consumers from " + table); - Assert.assertEquals(formatter.getParseResult().getTable(), table); - } - - @Test - public void showDatabases() - { - SqlBaseFormatter formatter = new SqlBaseFormatter("show databases"); - Assert.assertTrue(formatter.getParseResult().getToken().equals("SHOW")); - } - - @Test - public void showTables() - { - SqlBaseFormatter formatter = new SqlBaseFormatter("show tables"); - Assert.assertTrue(formatter.getParseResult().getChildToken().equals("TABLES")); - - formatter = new SqlBaseFormatter("show tables from " + table); - Assert.assertEquals(formatter.getParseResult().getTable(), table); - } -} diff --git a/core/datacap-parser/src/test/java/io/edurt/datacap/sql/ShowPathsTest.java b/core/datacap-parser/src/test/java/io/edurt/datacap/sql/ShowPathsTest.java deleted file mode 100644 index b27396678e..0000000000 --- a/core/datacap-parser/src/test/java/io/edurt/datacap/sql/ShowPathsTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.edurt.datacap.sql; - -import org.junit.Assert; -import org.junit.Test; - -public class ShowPathsTest -{ - @Test - public void testShowPaths() - { - SqlBaseFormatter formatter = new SqlBaseFormatter("show paths"); - Assert.assertTrue(formatter.getParseResult().isSuccessful()); - - formatter = new SqlBaseFormatter("SHOW PATHS"); - Assert.assertTrue(formatter.getParseResult().isSuccessful()); - } - @Test - public void testShowPathsFrom() - { - SqlBaseFormatter formatter = new SqlBaseFormatter("show paths from aa"); - Assert.assertTrue(formatter.getParseResult().isSuccessful()); - - formatter = new SqlBaseFormatter("SHOW PATHS FROM aaa"); - Assert.assertTrue(formatter.getParseResult().isSuccessful()); - } -} \ No newline at end of file diff --git a/core/datacap-parser/src/test/java/io/edurt/datacap/sql/SqlBaseFormatterTest.java b/core/datacap-parser/src/test/java/io/edurt/datacap/sql/SqlBaseFormatterTest.java deleted file mode 100644 index 0fb988fb41..0000000000 --- a/core/datacap-parser/src/test/java/io/edurt/datacap/sql/SqlBaseFormatterTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.edurt.datacap.sql; - -import org.junit.Assert; -import org.junit.Test; - -public class SqlBaseFormatterTest -{ - @Test - public void getParseResult() - { - String sql = "SELECT * FROM a"; - SqlBaseFormatter formatter = new SqlBaseFormatter(sql); - Assert.assertTrue(formatter.getParseResult().isSuccessful()); - } -} \ No newline at end of file diff --git a/core/datacap-service/src/main/java/io/edurt/datacap/service/security/UserDetailsService.java b/core/datacap-service/src/main/java/io/edurt/datacap/service/security/UserDetailsService.java index bcbefa67bf..111b910166 100644 --- a/core/datacap-service/src/main/java/io/edurt/datacap/service/security/UserDetailsService.java +++ b/core/datacap-service/src/main/java/io/edurt/datacap/service/security/UserDetailsService.java @@ -48,6 +48,7 @@ public UserDetailsService(Long id, String code, String username, String password public static UserDetailsService build(UserEntity user) { + // TODO: Add no code alert List authorities = user.getRoles().stream() .map(role -> new SimpleGrantedAuthority(role.getCode())) .collect(Collectors.toList()); diff --git a/docs/docs/release/latest.en.md b/docs/docs/release/latest.en.md index de38e8d309..814972ee19 100644 --- a/docs/docs/release/latest.en.md +++ b/docs/docs/release/latest.en.md @@ -1,12 +1,19 @@ **DataCap Released!** -| Release Version | Published | -|:--------:|:------------:| -| `2024.4` | `2024-12-02` | +| Release Version | Published | +|:---------------:|:------------:| +| `2024.4.0` | `2024-12-02` | !!! note -This is a brand new version that uses a new plugin management system, new APIs, and other new features. This update is a new version and is not compatible with the previous version. Make a backup of your data before upgrading to avoid data loss. The database is compatible, as long as the upgraded SQL is executed. + This is a brand new version that uses a new plugin management system, new APIs, and other new features. This update is a new version and is not compatible with the previous version. Make a backup of your data before upgrading to avoid data loss. The database is compatible, as long as the upgraded SQL is executed.
+ It should also be noted that after upgrading the version, you need to modify the value of the 'code' field of the 'datacap_user' and 'datacap_role' tables, which is unique for each piece of data, otherwise it will cause you to be unable to log in. (If it is a clean installation, you can ignore this step)
+ Execute the following SQL statement to upgrade the database:
+ ```sql + INSERT INTO `datacap_menu` VALUES + (18,'全局 - 商店','STORE','','/store','',3,'VIEW',0,1,'common.store','Store',NULL,'2024-11-05 21:18:28',0,0,NULL); + INSERT INTO `datacap_role_menu_relation` VALUES ('1','18') + ``` #### Key features diff --git a/docs/docs/release/latest.md b/docs/docs/release/latest.md index 7d5b96afa9..47d109e44d 100644 --- a/docs/docs/release/latest.md +++ b/docs/docs/release/latest.md @@ -1,12 +1,19 @@ **DataCap 发布!** -| 发布版本 | 发布时间 | -|:--------:|:------------:| -| `2024.4` | `2024-12-02` | +| 发布版本 | 发布时间 | +|:----------:|:------------:| +| `2024.4.0` | `2024-12-02` | !!! note - 本版本是一个全新的版本,完全使用了新的插件管理系统,新的 API 等各种新特性。本次更新为全新的版本,不兼容之前的版本。升级前要做好数据备份,以免数据丢失。数据库是兼容的,只要执行升级的 SQL 就可以了。 + 本版本是一个全新的版本,完全使用了新的插件管理系统,新的 API 等各种新特性。本次更新为全新的版本,不兼容之前的版本。升级前要做好数据备份,以免数据丢失。数据库是兼容的,只要执行升级的 SQL 就可以了。
+ 还需要注意的是升级版本后,要修改 `datacap_user` 和 `datacap_role` 表的 `code` 字段的值每条数据唯一即可,否则会导致无法登录。(如果是全新安装可忽略这个步骤)
+ 执行以下 SQL 语句升级数据库:
+ ```sql + INSERT INTO `datacap_menu` VALUES + (18,'全局 - 商店','STORE','','/store','',3,'VIEW',0,1,'common.store','Store',NULL,'2024-11-05 21:18:28',0,0,NULL); + INSERT INTO `datacap_role_menu_relation` VALUES ('1','18') + ``` #### 主要功能 diff --git a/driver/datacap-driver-mongodb/pom.xml b/driver/datacap-driver-mongodb/pom.xml new file mode 100644 index 0000000000..342e02ff1a --- /dev/null +++ b/driver/datacap-driver-mongodb/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + io.edurt.datacap + datacap + 2024.4.1-SNAPSHOT + ../../pom.xml + + + datacap-driver-mongodb + DataCap - MongoDB - Driver + + + + org.mongodb + mongodb-driver-sync + + + ch.qos.logback + logback-classic + ${logback.version} + + + diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoConnection.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoConnection.java new file mode 100644 index 0000000000..8727d58c7b --- /dev/null +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoConnection.java @@ -0,0 +1,474 @@ +package io.edurt.datacap.driver; + +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoDatabase; +import lombok.Getter; + +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Struct; +import java.util.Collections; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; + +public class MongoConnection + implements Connection +{ + @Getter + private final MongoDatabase database; + private final MongoClient mongoClient; + private boolean isClosed = false; + + // Constructor to establish MongoDB connection + // 构造函数用于建立MongoDB连接 + public MongoConnection(String url, Properties info) + throws SQLException + { + try { + String databaseName = info.getProperty("authDatabase", "admin"); + + // 如果URL中包含认证信息,直接使用URL创建客户端 + // If the URL contains authentication information, create a client directly using the URL + if (url.contains("@")) { + this.mongoClient = MongoClients.create(url); + } + else { + // 否则检查Properties中的认证信息 + // Otherwise, check the authentication information in Properties + String username = info.getProperty("user"); + String password = info.getProperty("password"); + + if (username != null && password != null) { + // 创建认证凭证 + // Create authentication credentials + MongoCredential credential = MongoCredential.createCredential( + username, + databaseName, + password.toCharArray() + ); + + // 解析主机和端口 + // Parse host and port + String[] hostPort = url.split("://")[1].split(":"); + String host = hostPort[0]; + int port = hostPort.length > 1 ? Integer.parseInt(hostPort[1]) : 27017; + + // 创建带认证的客户端设置 + // Create client settings with authentication + MongoClientSettings settings = MongoClientSettings.builder() + .credential(credential) + .applyToClusterSettings(builder -> + builder.hosts(Collections.singletonList(new ServerAddress(host, port)))) + .build(); + + this.mongoClient = MongoClients.create(settings); + } + else { + // 无认证信息,直接连接 + // No authentication information, connect directly + this.mongoClient = MongoClients.create(url); + } + } + + this.database = mongoClient.getDatabase(databaseName); + + // 验证连接 + // Verify connection + database.runCommand(new org.bson.Document("ping", 1)); + } + catch (Exception e) { + throw new SQLException("Failed to connect to MongoDB: " + e.getMessage(), e); + } + } + + // Create statement for executing queries + // 创建用于执行查询的Statement + @Override + public Statement createStatement() + throws SQLException + { + checkClosed(); + return new MongoStatement(this); + } + + @Override + public PreparedStatement prepareStatement(String sql) + throws SQLException + { + return null; + } + + @Override + public CallableStatement prepareCall(String sql) + throws SQLException + { + return null; + } + + @Override + public String nativeSQL(String sql) + throws SQLException + { + return ""; + } + + // Check if connection is closed + // 检查连接是否已关闭 + private void checkClosed() + throws SQLException + { + if (isClosed) { + throw new SQLException("Connection is closed"); + } + } + + // Close the connection + // 关闭连接 + @Override + public void close() + throws SQLException + { + if (!isClosed) { + mongoClient.close(); + isClosed = true; + } + } + + // Check if connection is closed + // 检查连接是否已关闭 + @Override + public boolean isClosed() + throws SQLException + { + return isClosed; + } + + @Override + public DatabaseMetaData getMetaData() + throws SQLException + { + throw new SQLFeatureNotSupportedException("Method not supported"); + } + + @Override + public void setReadOnly(boolean readOnly) + throws SQLException + {} + + @Override + public boolean isReadOnly() + throws SQLException + { + return false; + } + + @Override + public void setCatalog(String catalog) + throws SQLException + {} + + @Override + public String getCatalog() + throws SQLException + { + return ""; + } + + @Override + public void setTransactionIsolation(int level) + throws SQLException + {} + + @Override + public int getTransactionIsolation() + throws SQLException + { + return 0; + } + + @Override + public SQLWarning getWarnings() + throws SQLException + { + return null; + } + + @Override + public void clearWarnings() + throws SQLException + {} + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) + throws SQLException + { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException + { + return null; + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException + { + return null; + } + + @Override + public Map> getTypeMap() + throws SQLException + { + return Map.of(); + } + + @Override + public void setTypeMap(Map> map) + throws SQLException + { + + } + + @Override + public void setHoldability(int holdability) + throws SQLException + { + + } + + @Override + public int getHoldability() + throws SQLException + { + return 0; + } + + @Override + public Savepoint setSavepoint() + throws SQLException + { + return null; + } + + @Override + public Savepoint setSavepoint(String name) + throws SQLException + { + return null; + } + + @Override + public void rollback(Savepoint savepoint) + throws SQLException + {} + + @Override + public void releaseSavepoint(Savepoint savepoint) + throws SQLException + {} + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException + { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException + { + return null; + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException + { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) + throws SQLException + { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) + throws SQLException + { + return null; + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) + throws SQLException + { + return null; + } + + @Override + public Clob createClob() + throws SQLException + { + return null; + } + + @Override + public Blob createBlob() + throws SQLException + { + return null; + } + + @Override + public NClob createNClob() + throws SQLException + { + return null; + } + + @Override + public SQLXML createSQLXML() + throws SQLException + { + return null; + } + + @Override + public boolean isValid(int timeout) + throws SQLException + { + return false; + } + + @Override + public void setClientInfo(String name, String value) + throws SQLClientInfoException + {} + + @Override + public void setClientInfo(Properties properties) + throws SQLClientInfoException + {} + + @Override + public String getClientInfo(String name) + throws SQLException + { + return ""; + } + + @Override + public Properties getClientInfo() + throws SQLException + { + return null; + } + + @Override + public Array createArrayOf(String typeName, Object[] elements) + throws SQLException + { + return null; + } + + @Override + public Struct createStruct(String typeName, Object[] attributes) + throws SQLException + { + return null; + } + + @Override + public void setSchema(String schema) + throws SQLException + {} + + @Override + public String getSchema() + throws SQLException + { + return ""; + } + + @Override + public void abort(Executor executor) + throws SQLException + {} + + @Override + public void setNetworkTimeout(Executor executor, int milliseconds) + throws SQLException + {} + + @Override + public int getNetworkTimeout() + throws SQLException + { + return 0; + } + + @Override + public void setAutoCommit(boolean autoCommit) + throws SQLException + { + // MongoDB doesn't support transactions in the same way as relational databases + // MongoDB 不支持与关系数据库相同的事务 + } + + @Override + public boolean getAutoCommit() + throws SQLException + { + return true; + } + + @Override + public void commit() + throws SQLException + {} + + @Override + public void rollback() + throws SQLException + {} + + @Override + public T unwrap(Class iface) + throws SQLException + { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) + throws SQLException + { + return false; + } +} diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoJdbcDriver.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoJdbcDriver.java new file mode 100644 index 0000000000..b1d6261287 --- /dev/null +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoJdbcDriver.java @@ -0,0 +1,93 @@ +package io.edurt.datacap.driver; + +import java.sql.Connection; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.DriverPropertyInfo; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.Properties; +import java.util.logging.Logger; + +public class MongoJdbcDriver + implements Driver +{ + // Static initialization of driver + // 静态初始化驱动 + static { + try { + DriverManager.registerDriver(new MongoJdbcDriver()); + } + catch (SQLException e) { + throw new RuntimeException("Can't register MongoDB JDBC Driver", e); + } + } + + // Check if this driver can handle the given URL + // 检查驱动是否可以处理给定的URL + @Override + public boolean acceptsURL(String url) + throws SQLException + { + return url != null && ( + url.startsWith("jdbc:mongo:") + || url.startsWith("jdbc:mongodb:") + || url.startsWith("jdbc:mongodb+srv:") + ); + } + + // Connect to MongoDB database + // 连接MongoDB数据库 + @Override + public Connection connect(String url, Properties info) + throws SQLException + { + if (!acceptsURL(url)) { + return null; + } + + return new MongoConnection(url, info); + } + + // Get driver's major version + // 获取驱动主版本号 + @Override + public int getMajorVersion() + { + return 1; + } + + // Get driver's minor version + // 获取驱动次版本号 + @Override + public int getMinorVersion() + { + return 0; + } + + // Get driver's property info + // 获取驱动属性信息 + @Override + public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) + throws SQLException + { + return new DriverPropertyInfo[0]; + } + + // Check if driver is JDBC compliant + // 检查驱动是否符合JDBC规范 + @Override + public boolean jdbcCompliant() + { + return false; + } + + // Get parent logger + // 获取父日志记录器 + @Override + public Logger getParentLogger() + throws SQLFeatureNotSupportedException + { + throw new SQLFeatureNotSupportedException("Parent logger is not supported"); + } +} diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoQueryParser.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoQueryParser.java new file mode 100644 index 0000000000..41b48a0992 --- /dev/null +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoQueryParser.java @@ -0,0 +1,235 @@ +package io.edurt.datacap.driver; + +import lombok.Getter; +import org.bson.Document; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Getter +public class MongoQueryParser +{ + // Getters for parsed components + // 获取解析后的组件 + private String collection; + private Document query; + private Document update; + private List fields; + private Document sort; + private int limit = -1; + private int skip = -1; + + // SQL keywords pattern + // SQL关键字匹配模式 + private static final Pattern SELECT_PATTERN = + Pattern.compile("SELECT\\s+(.+?)\\s+FROM\\s+(\\w+)\\s*(?:WHERE\\s+(.+?))?\\s*(?:ORDER\\s+BY\\s+(.+?))?\\s*(?:LIMIT\\s+(\\d+))?\\s*(?:OFFSET\\s+(\\d+))?\\s*$", + Pattern.CASE_INSENSITIVE); + + private static final Pattern UPDATE_PATTERN = + Pattern.compile("UPDATE\\s+(\\w+)\\s+SET\\s+(.+?)(?:\\s+WHERE\\s+(.+))?", + Pattern.CASE_INSENSITIVE); + + // Constructor that parses SQL query + // 构造函数,解析SQL查询 + public MongoQueryParser(String sql) + { + parseSql(sql); + } + + // Parse SQL statement + // 解析SQL语句 + private void parseSql(String sql) + { + sql = sql.trim(); + + if (sql.toUpperCase().startsWith("SELECT")) { + parseSelectStatement(sql); + } + else if (sql.toUpperCase().startsWith("UPDATE")) { + parseUpdateStatement(sql); + } + else { + throw new IllegalArgumentException("Unsupported SQL operation: " + sql); + } + } + + // Parse SELECT statement + // 解析SELECT语句 + private void parseSelectStatement(String sql) + { + Matcher matcher = SELECT_PATTERN.matcher(sql); + if (!matcher.find()) { + throw new IllegalArgumentException("Invalid SELECT statement: " + sql); + } + + // Parse fields + // 解析字段 + String fieldsList = matcher.group(1); + this.fields = new ArrayList<>(); + if (!fieldsList.equals("*")) { + Arrays.stream(fieldsList.split(",")) + .map(String::trim) + .forEach(fields::add); + } + + // Get collection name + // 获取集合名称 + this.collection = matcher.group(2); + + // Parse WHERE clause + // 解析WHERE子句 + String whereClause = matcher.group(3); + this.query = whereClause != null ? parseWhereClause(whereClause) : new Document(); + + // Parse ORDER BY + // 解析ORDER BY + String orderBy = matcher.group(4); + if (orderBy != null) { + this.sort = parseOrderBy(orderBy); + } + + // Parse LIMIT and OFFSET + // 解析LIMIT和OFFSET + String limitStr = matcher.group(5); + if (limitStr != null) { + this.limit = Integer.parseInt(limitStr); + } + + String offsetStr = matcher.group(6); + if (offsetStr != null) { + this.skip = Integer.parseInt(offsetStr); + } + } + + // Parse UPDATE statement + // 解析UPDATE语句 + private void parseUpdateStatement(String sql) + { + Matcher matcher = UPDATE_PATTERN.matcher(sql); + if (!matcher.find()) { + throw new IllegalArgumentException("Invalid UPDATE statement: " + sql); + } + + // Get collection name + // 获取集合名称 + this.collection = matcher.group(1); + + // Parse SET clause + // 解析SET子句 + String setClause = matcher.group(2); + this.update = parseSetClause(setClause); + + // Parse WHERE clause + // 解析WHERE子句 + String whereClause = matcher.group(3); + this.query = whereClause != null ? parseWhereClause(whereClause) : new Document(); + } + + // Parse WHERE clause to MongoDB query + // 解析WHERE子句转换为MongoDB查询 + private Document parseWhereClause(String whereClause) + { + Document query = new Document(); + String[] conditions = whereClause.split("AND"); + + for (String condition : conditions) { + condition = condition.trim(); + + // Handle different operators + // 处理不同的操作符 + if (condition.contains("=")) { + String[] parts = condition.split("="); + query.put(parts[0].trim(), parseValue(parts[1].trim())); + } + else if (condition.contains(">")) { + String[] parts = condition.split(">"); + query.put(parts[0].trim(), new Document("$gt", parseValue(parts[1].trim()))); + } + else if (condition.contains("<")) { + String[] parts = condition.split("<"); + query.put(parts[0].trim(), new Document("$lt", parseValue(parts[1].trim()))); + } + else if (condition.toLowerCase().contains("like")) { + String[] parts = condition.split("LIKE", 2); + String pattern = parts[1].trim().replaceAll("%", ".*").replaceAll("'", ""); + query.put(parts[0].trim(), Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); + } + } + + return query; + } + + // Parse SET clause for UPDATE statement + // 解析UPDATE语句的SET子句 + private Document parseSetClause(String setClause) + { + Document updateDoc = new Document(); + Document setDoc = new Document(); + + String[] setPairs = setClause.split(","); + for (String setPair : setPairs) { + String[] parts = setPair.trim().split("="); + String field = parts[0].trim(); + Object value = parseValue(parts[1].trim()); + setDoc.put(field, value); + } + + updateDoc.put("$set", setDoc); + return updateDoc; + } + + // Parse ORDER BY clause + // 解析ORDER BY子句 + private Document parseOrderBy(String orderByClause) + { + Document orderBy = new Document(); + String[] parts = orderByClause.split(","); + + for (String part : parts) { + part = part.trim(); + if (part.toUpperCase().endsWith("DESC")) { + String field = part.substring(0, part.length() - 4).trim(); + orderBy.put(field, -1); + } + else { + String field = part.toUpperCase().endsWith("ASC") ? + part.substring(0, part.length() - 3).trim() : part; + orderBy.put(field.trim(), 1); + } + } + + return orderBy; + } + + // Parse string value to appropriate type + // 将字符串值解析为适当的类型 + private Object parseValue(String value) + { + value = value.trim(); + + // Remove quotes if present + // 如果有引号则移除 + if (value.startsWith("'") && value.endsWith("'")) { + return value.substring(1, value.length() - 1); + } + + // Try parsing as number + // 尝试解析为数字 + try { + if (value.contains(".")) { + return Double.parseDouble(value); + } + else { + return Long.parseLong(value); + } + } + catch (NumberFormatException e) { + // Return as string if not a number + // 如果不是数字则返回字符串 + return value; + } + } +} diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoResultSet.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoResultSet.java new file mode 100644 index 0000000000..ec688bdef0 --- /dev/null +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoResultSet.java @@ -0,0 +1,1424 @@ +package io.edurt.datacap.driver; + +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoCursor; +import org.bson.Document; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.NClob; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.Map; + +public class MongoResultSet + implements ResultSet +{ + private final MongoCursor cursor; + private Document current; + private boolean isClosed = false; + private final List columnNames; + + // Constructor + // 构造函数 + public MongoResultSet(FindIterable result) + { + this.cursor = result.iterator(); + this.columnNames = new ArrayList<>(); + if (cursor.hasNext()) { + Document first = cursor.next(); + columnNames.addAll(first.keySet()); + this.current = first; + } + } + + // Move to next row + // 移动到下一行 + @Override + public boolean next() + throws SQLException + { + checkClosed(); + if (cursor.hasNext()) { + current = cursor.next(); + return true; + } + return false; + } + + // Get string value by column name + // 通过列名获取字符串值 + @Override + public String getString(String columnLabel) + throws SQLException + { + checkClosed(); + Object value = current.get(columnLabel); + return value == null ? null : value.toString(); + } + + @Override + public boolean getBoolean(String columnLabel) + throws SQLException + { + return false; + } + + @Override + public byte getByte(String columnLabel) + throws SQLException + { + return 0; + } + + @Override + public short getShort(String columnLabel) + throws SQLException + { + return 0; + } + + // Get integer value by column name + // 通过列名获取整数值 + @Override + public int getInt(String columnLabel) + throws SQLException + { + checkClosed(); + Object value = current.get(columnLabel); + if (value == null) { + throw new SQLException("Null value"); + } + if (value instanceof Number) { + return ((Number) value).intValue(); + } + throw new SQLException("Invalid type for integer column"); + } + + @Override + public long getLong(String columnLabel) + throws SQLException + { + return 0; + } + + @Override + public float getFloat(String columnLabel) + throws SQLException + { + return 0; + } + + @Override + public double getDouble(String columnLabel) + throws SQLException + { + return 0; + } + + @Override + public BigDecimal getBigDecimal(String columnLabel, int scale) + throws SQLException + { + return null; + } + + @Override + public byte[] getBytes(String columnLabel) + throws SQLException + { + return new byte[0]; + } + + @Override + public Date getDate(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public Time getTime(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public Timestamp getTimestamp(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public InputStream getAsciiStream(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public InputStream getUnicodeStream(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public InputStream getBinaryStream(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public SQLWarning getWarnings() + throws SQLException + { + return null; + } + + @Override + public void clearWarnings() + throws SQLException + { + + } + + @Override + public String getCursorName() + throws SQLException + { + return ""; + } + + @Override + public ResultSetMetaData getMetaData() + throws SQLException + { + return null; + } + + @Override + public Object getObject(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public Object getObject(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public int findColumn(String columnLabel) + throws SQLException + { + return 0; + } + + @Override + public Reader getCharacterStream(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public Reader getCharacterStream(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public BigDecimal getBigDecimal(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public BigDecimal getBigDecimal(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public boolean isBeforeFirst() + throws SQLException + { + return false; + } + + @Override + public boolean isAfterLast() + throws SQLException + { + return false; + } + + @Override + public boolean isFirst() + throws SQLException + { + return false; + } + + @Override + public boolean isLast() + throws SQLException + { + return false; + } + + @Override + public void beforeFirst() + throws SQLException + { + + } + + @Override + public void afterLast() + throws SQLException + { + + } + + @Override + public boolean first() + throws SQLException + { + return false; + } + + @Override + public boolean last() + throws SQLException + { + return false; + } + + @Override + public int getRow() + throws SQLException + { + return 0; + } + + @Override + public boolean absolute(int row) + throws SQLException + { + return false; + } + + @Override + public boolean relative(int rows) + throws SQLException + { + return false; + } + + @Override + public boolean previous() + throws SQLException + { + return false; + } + + @Override + public void setFetchDirection(int direction) + throws SQLException + { + + } + + @Override + public int getFetchDirection() + throws SQLException + { + return 0; + } + + @Override + public void setFetchSize(int rows) + throws SQLException + { + + } + + @Override + public int getFetchSize() + throws SQLException + { + return 0; + } + + @Override + public int getType() + throws SQLException + { + return 0; + } + + @Override + public int getConcurrency() + throws SQLException + { + return 0; + } + + @Override + public boolean rowUpdated() + throws SQLException + { + return false; + } + + @Override + public boolean rowInserted() + throws SQLException + { + return false; + } + + @Override + public boolean rowDeleted() + throws SQLException + { + return false; + } + + @Override + public void updateNull(int columnIndex) + throws SQLException + { + + } + + @Override + public void updateBoolean(int columnIndex, boolean x) + throws SQLException + { + + } + + @Override + public void updateByte(int columnIndex, byte x) + throws SQLException + { + + } + + @Override + public void updateShort(int columnIndex, short x) + throws SQLException + { + + } + + @Override + public void updateInt(int columnIndex, int x) + throws SQLException + { + + } + + @Override + public void updateLong(int columnIndex, long x) + throws SQLException + { + + } + + @Override + public void updateFloat(int columnIndex, float x) + throws SQLException + { + + } + + @Override + public void updateDouble(int columnIndex, double x) + throws SQLException + { + + } + + @Override + public void updateBigDecimal(int columnIndex, BigDecimal x) + throws SQLException + { + + } + + @Override + public void updateString(int columnIndex, String x) + throws SQLException + { + + } + + @Override + public void updateBytes(int columnIndex, byte[] x) + throws SQLException + { + + } + + @Override + public void updateDate(int columnIndex, Date x) + throws SQLException + { + + } + + @Override + public void updateTime(int columnIndex, Time x) + throws SQLException + { + + } + + @Override + public void updateTimestamp(int columnIndex, Timestamp x) + throws SQLException + { + + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x, int length) + throws SQLException + { + + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x, int length) + throws SQLException + { + + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x, int length) + throws SQLException + { + + } + + @Override + public void updateObject(int columnIndex, Object x, int scaleOrLength) + throws SQLException + { + + } + + @Override + public void updateObject(int columnIndex, Object x) + throws SQLException + { + + } + + @Override + public void updateNull(String columnLabel) + throws SQLException + { + + } + + @Override + public void updateBoolean(String columnLabel, boolean x) + throws SQLException + { + + } + + @Override + public void updateByte(String columnLabel, byte x) + throws SQLException + { + + } + + @Override + public void updateShort(String columnLabel, short x) + throws SQLException + { + + } + + @Override + public void updateInt(String columnLabel, int x) + throws SQLException + { + + } + + @Override + public void updateLong(String columnLabel, long x) + throws SQLException + { + + } + + @Override + public void updateFloat(String columnLabel, float x) + throws SQLException + { + + } + + @Override + public void updateDouble(String columnLabel, double x) + throws SQLException + { + + } + + @Override + public void updateBigDecimal(String columnLabel, BigDecimal x) + throws SQLException + { + + } + + @Override + public void updateString(String columnLabel, String x) + throws SQLException + { + + } + + @Override + public void updateBytes(String columnLabel, byte[] x) + throws SQLException + { + + } + + @Override + public void updateDate(String columnLabel, Date x) + throws SQLException + { + + } + + @Override + public void updateTime(String columnLabel, Time x) + throws SQLException + { + + } + + @Override + public void updateTimestamp(String columnLabel, Timestamp x) + throws SQLException + { + + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x, int length) + throws SQLException + { + + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x, int length) + throws SQLException + { + + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader, int length) + throws SQLException + { + + } + + @Override + public void updateObject(String columnLabel, Object x, int scaleOrLength) + throws SQLException + { + + } + + @Override + public void updateObject(String columnLabel, Object x) + throws SQLException + { + + } + + @Override + public void insertRow() + throws SQLException + { + + } + + @Override + public void updateRow() + throws SQLException + { + + } + + @Override + public void deleteRow() + throws SQLException + { + + } + + @Override + public void refreshRow() + throws SQLException + { + + } + + @Override + public void cancelRowUpdates() + throws SQLException + { + + } + + @Override + public void moveToInsertRow() + throws SQLException + { + + } + + @Override + public void moveToCurrentRow() + throws SQLException + { + + } + + @Override + public Statement getStatement() + throws SQLException + { + return null; + } + + @Override + public Object getObject(int columnIndex, Map> map) + throws SQLException + { + return null; + } + + @Override + public Ref getRef(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public Blob getBlob(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public Clob getClob(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public Array getArray(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public Object getObject(String columnLabel, Map> map) + throws SQLException + { + return null; + } + + @Override + public Ref getRef(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public Blob getBlob(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public Clob getClob(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public Array getArray(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public Date getDate(int columnIndex, Calendar cal) + throws SQLException + { + return null; + } + + @Override + public Date getDate(String columnLabel, Calendar cal) + throws SQLException + { + return null; + } + + @Override + public Time getTime(int columnIndex, Calendar cal) + throws SQLException + { + return null; + } + + @Override + public Time getTime(String columnLabel, Calendar cal) + throws SQLException + { + return null; + } + + @Override + public Timestamp getTimestamp(int columnIndex, Calendar cal) + throws SQLException + { + return null; + } + + @Override + public Timestamp getTimestamp(String columnLabel, Calendar cal) + throws SQLException + { + return null; + } + + @Override + public URL getURL(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public URL getURL(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public void updateRef(int columnIndex, Ref x) + throws SQLException + { + + } + + @Override + public void updateRef(String columnLabel, Ref x) + throws SQLException + { + + } + + @Override + public void updateBlob(int columnIndex, Blob x) + throws SQLException + { + + } + + @Override + public void updateBlob(String columnLabel, Blob x) + throws SQLException + { + + } + + @Override + public void updateClob(int columnIndex, Clob x) + throws SQLException + { + + } + + @Override + public void updateClob(String columnLabel, Clob x) + throws SQLException + { + + } + + @Override + public void updateArray(int columnIndex, Array x) + throws SQLException + { + + } + + @Override + public void updateArray(String columnLabel, Array x) + throws SQLException + { + + } + + @Override + public RowId getRowId(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public RowId getRowId(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public void updateRowId(int columnIndex, RowId x) + throws SQLException + { + + } + + @Override + public void updateRowId(String columnLabel, RowId x) + throws SQLException + { + + } + + @Override + public int getHoldability() + throws SQLException + { + return 0; + } + + @Override + public boolean isClosed() + throws SQLException + { + return false; + } + + @Override + public void updateNString(int columnIndex, String nString) + throws SQLException + { + + } + + @Override + public void updateNString(String columnLabel, String nString) + throws SQLException + { + + } + + @Override + public void updateNClob(int columnIndex, NClob nClob) + throws SQLException + { + + } + + @Override + public void updateNClob(String columnLabel, NClob nClob) + throws SQLException + { + + } + + @Override + public NClob getNClob(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public NClob getNClob(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public SQLXML getSQLXML(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public SQLXML getSQLXML(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public void updateSQLXML(int columnIndex, SQLXML xmlObject) + throws SQLException + { + + } + + @Override + public void updateSQLXML(String columnLabel, SQLXML xmlObject) + throws SQLException + { + + } + + @Override + public String getNString(int columnIndex) + throws SQLException + { + return ""; + } + + @Override + public String getNString(String columnLabel) + throws SQLException + { + return ""; + } + + @Override + public Reader getNCharacterStream(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public Reader getNCharacterStream(String columnLabel) + throws SQLException + { + return null; + } + + @Override + public void updateNCharacterStream(int columnIndex, Reader x, long length) + throws SQLException + { + + } + + @Override + public void updateNCharacterStream(String columnLabel, Reader reader, long length) + throws SQLException + { + + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x, long length) + throws SQLException + { + + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x, long length) + throws SQLException + { + + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x, long length) + throws SQLException + { + + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x, long length) + throws SQLException + { + + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x, long length) + throws SQLException + { + + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader, long length) + throws SQLException + { + + } + + @Override + public void updateBlob(int columnIndex, InputStream inputStream, long length) + throws SQLException + { + + } + + @Override + public void updateBlob(String columnLabel, InputStream inputStream, long length) + throws SQLException + { + + } + + @Override + public void updateClob(int columnIndex, Reader reader, long length) + throws SQLException + { + + } + + @Override + public void updateClob(String columnLabel, Reader reader, long length) + throws SQLException + { + + } + + @Override + public void updateNClob(int columnIndex, Reader reader, long length) + throws SQLException + { + + } + + @Override + public void updateNClob(String columnLabel, Reader reader, long length) + throws SQLException + { + + } + + @Override + public void updateNCharacterStream(int columnIndex, Reader x) + throws SQLException + { + + } + + @Override + public void updateNCharacterStream(String columnLabel, Reader reader) + throws SQLException + { + + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x) + throws SQLException + { + + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x) + throws SQLException + { + + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x) + throws SQLException + { + + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x) + throws SQLException + { + + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x) + throws SQLException + { + + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader) + throws SQLException + { + + } + + @Override + public void updateBlob(int columnIndex, InputStream inputStream) + throws SQLException + { + + } + + @Override + public void updateBlob(String columnLabel, InputStream inputStream) + throws SQLException + { + + } + + @Override + public void updateClob(int columnIndex, Reader reader) + throws SQLException + { + + } + + @Override + public void updateClob(String columnLabel, Reader reader) + throws SQLException + { + + } + + @Override + public void updateNClob(int columnIndex, Reader reader) + throws SQLException + { + + } + + @Override + public void updateNClob(String columnLabel, Reader reader) + throws SQLException + { + + } + + @Override + public T getObject(int columnIndex, Class type) + throws SQLException + { + return null; + } + + @Override + public T getObject(String columnLabel, Class type) + throws SQLException + { + return null; + } + + // Check if result set is closed + // 检查结果集是否已关闭 + private void checkClosed() + throws SQLException + { + if (isClosed) { + throw new SQLException("ResultSet is closed"); + } + } + + // Close the result set + // 关闭结果集 + @Override + public void close() + throws SQLException + { + if (!isClosed) { + cursor.close(); + isClosed = true; + } + } + + @Override + public boolean wasNull() + throws SQLException + { + return false; + } + + @Override + public String getString(int columnIndex) + throws SQLException + { + return ""; + } + + @Override + public boolean getBoolean(int columnIndex) + throws SQLException + { + return false; + } + + @Override + public byte getByte(int columnIndex) + throws SQLException + { + return 0; + } + + @Override + public short getShort(int columnIndex) + throws SQLException + { + return 0; + } + + @Override + public int getInt(int columnIndex) + throws SQLException + { + return 0; + } + + @Override + public long getLong(int columnIndex) + throws SQLException + { + return 0; + } + + @Override + public float getFloat(int columnIndex) + throws SQLException + { + return 0; + } + + @Override + public double getDouble(int columnIndex) + throws SQLException + { + return 0; + } + + @Override + public BigDecimal getBigDecimal(int columnIndex, int scale) + throws SQLException + { + return null; + } + + @Override + public byte[] getBytes(int columnIndex) + throws SQLException + { + return new byte[0]; + } + + @Override + public Date getDate(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public Time getTime(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public Timestamp getTimestamp(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public InputStream getAsciiStream(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public InputStream getUnicodeStream(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public InputStream getBinaryStream(int columnIndex) + throws SQLException + { + return null; + } + + @Override + public T unwrap(Class iface) + throws SQLException + { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) + throws SQLException + { + return false; + } +} diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoStatement.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoStatement.java new file mode 100644 index 0000000000..fe13ff449a --- /dev/null +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoStatement.java @@ -0,0 +1,352 @@ +package io.edurt.datacap.driver; + +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoCollection; +import lombok.extern.slf4j.Slf4j; +import org.bson.Document; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Statement; + +@Slf4j +public class MongoStatement + implements Statement +{ + private final MongoConnection connection; + private boolean isClosed = false; + + // Constructor + // 构造函数 + public MongoStatement(MongoConnection connection) + { + this.connection = connection; + } + + // Execute query and return ResultSet + // 执行查询并返回ResultSet + @Override + public ResultSet executeQuery(String sql) + throws SQLException + { + checkClosed(); + try { + // Parse SQL to MongoDB query + // 将SQL解析为MongoDB查询 + MongoQueryParser parser = new MongoQueryParser(sql); + String collectionName = parser.getCollection(); + Document query = parser.getQuery(); + log.debug("Executing query: {}", query); + + MongoCollection collection = connection.getDatabase().getCollection(collectionName); + FindIterable result = collection.find(query); + + return new MongoResultSet(result); + } + catch (Exception e) { + throw new SQLException("Failed to execute query", e); + } + } + + // Execute update statement + // 执行更新语句 + @Override + public int executeUpdate(String sql) + throws SQLException + { + checkClosed(); + try { + MongoQueryParser parser = new MongoQueryParser(sql); + String collectionName = parser.getCollection(); + Document update = parser.getUpdate(); + + MongoCollection collection = connection.getDatabase().getCollection(collectionName); + return (int) collection.updateMany(parser.getQuery(), update).getModifiedCount(); + } + catch (Exception e) { + throw new SQLException("Failed to execute update", e); + } + } + + // Check if statement is closed + // 检查语句是否已关闭 + private void checkClosed() + throws SQLException + { + if (isClosed) { + throw new SQLException("Statement is closed"); + } + } + + // Close the statement + // 关闭语句 + @Override + public void close() + throws SQLException + { + isClosed = true; + } + + @Override + public int getMaxFieldSize() + throws SQLException + { + return 0; + } + + @Override + public void setMaxFieldSize(int max) + throws SQLException + {} + + @Override + public int getMaxRows() + throws SQLException + { + return 0; + } + + @Override + public void setMaxRows(int max) + throws SQLException + {} + + @Override + public void setEscapeProcessing(boolean enable) + throws SQLException + {} + + @Override + public int getQueryTimeout() + throws SQLException + { + return 0; + } + + @Override + public void setQueryTimeout(int seconds) + throws SQLException + {} + + @Override + public void cancel() + throws SQLException + {} + + @Override + public SQLWarning getWarnings() + throws SQLException + { + return null; + } + + @Override + public void clearWarnings() + throws SQLException + {} + + @Override + public void setCursorName(String name) + throws SQLException + {} + + @Override + public boolean execute(String sql) + throws SQLException + { + return false; + } + + @Override + public ResultSet getResultSet() + throws SQLException + { + return null; + } + + @Override + public int getUpdateCount() + throws SQLException + { + return 0; + } + + @Override + public boolean getMoreResults() + throws SQLException + { + return false; + } + + @Override + public void setFetchDirection(int direction) + throws SQLException + {} + + @Override + public int getFetchDirection() + throws SQLException + { + return 0; + } + + @Override + public void setFetchSize(int rows) + throws SQLException + {} + + @Override + public int getFetchSize() + throws SQLException + { + return 0; + } + + @Override + public int getResultSetConcurrency() + throws SQLException + { + return 0; + } + + @Override + public int getResultSetType() + throws SQLException + { + return 0; + } + + @Override + public void addBatch(String sql) + throws SQLException + {} + + @Override + public void clearBatch() + throws SQLException + {} + + @Override + public int[] executeBatch() + throws SQLException + { + return new int[0]; + } + + @Override + public Connection getConnection() + throws SQLException + { + return null; + } + + @Override + public boolean getMoreResults(int current) + throws SQLException + { + return false; + } + + @Override + public ResultSet getGeneratedKeys() + throws SQLException + { + return null; + } + + @Override + public int executeUpdate(String sql, int autoGeneratedKeys) + throws SQLException + { + return 0; + } + + @Override + public int executeUpdate(String sql, int[] columnIndexes) + throws SQLException + { + return 0; + } + + @Override + public int executeUpdate(String sql, String[] columnNames) + throws SQLException + { + return 0; + } + + @Override + public boolean execute(String sql, int autoGeneratedKeys) + throws SQLException + { + return false; + } + + @Override + public boolean execute(String sql, int[] columnIndexes) + throws SQLException + { + return false; + } + + @Override + public boolean execute(String sql, String[] columnNames) + throws SQLException + { + return false; + } + + @Override + public int getResultSetHoldability() + throws SQLException + { + return 0; + } + + @Override + public boolean isClosed() + throws SQLException + { + return false; + } + + @Override + public void setPoolable(boolean poolable) + throws SQLException + {} + + @Override + public boolean isPoolable() + throws SQLException + { + return false; + } + + @Override + public void closeOnCompletion() + throws SQLException + {} + + @Override + public boolean isCloseOnCompletion() + throws SQLException + { + return false; + } + + @Override + public T unwrap(Class iface) + throws SQLException + { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) + throws SQLException + { + return false; + } +} diff --git a/pom.xml b/pom.xml index d1cf565296..fc71e9d284 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ lib/datacap-schedule driver/datacap-driver-redis driver/datacap-driver-mongo + driver/datacap-driver-mongodb shaded/datacap-shaded-ydb shaded/datacap-shaded-pinot shaded/datacap-shaded-neo4j @@ -109,6 +110,8 @@ test/datacap-test-executor test/datacap-test-scheduler test/datacap-test-fs + test/datacap-test-driver + test/datacap-test-parser
datacap @@ -199,6 +202,7 @@ 1.20.1 2.3.2 2.1.214 + 4.11.1 3.6.0 0.10.2 @@ -409,6 +413,11 @@ commons-io ${datacap.commons-io.version} + + org.mongodb + mongodb-driver-sync + ${mongodb-driver.version} + diff --git a/test/datacap-test-driver/pom.xml b/test/datacap-test-driver/pom.xml new file mode 100644 index 0000000000..d4bba55d6f --- /dev/null +++ b/test/datacap-test-driver/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + io.edurt.datacap + datacap + 2024.4.1-SNAPSHOT + + + datacap-test-driver + DataCap - Test - Driver + + + + io.edurt.datacap + datacap-driver-mongodb + ${project.version} + test + + + diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java new file mode 100644 index 0000000000..8d029cfcde --- /dev/null +++ b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java @@ -0,0 +1,41 @@ +package io.edurt.datacap.test.mongo; + +import org.junit.Test; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + +public class MongoJdbcDriverTest +{ + @Test + public void test() + { + try + { + Class.forName("io.edurt.datacap.driver.MongoJdbcDriver"); + + Properties props = new Properties(); + props.setProperty("authDatabase", "admin"); + props.setProperty("user", "mongoadmin"); + props.setProperty("password", "secret"); + props.setProperty("database", "local"); + Connection conn = DriverManager.getConnection("jdbc:mongodb://localhost:27017", props); + + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT hostname, startTime FROM startup_log"); + + while (rs.next()) + { + System.out.println(rs.getString("name")); + } + } + catch (ClassNotFoundException | SQLException e) + { + e.printStackTrace(); + } + } +} diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoQueryParserTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoQueryParserTest.java new file mode 100644 index 0000000000..80a0e85935 --- /dev/null +++ b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoQueryParserTest.java @@ -0,0 +1,34 @@ +package io.edurt.datacap.test.mongo; + +import io.edurt.datacap.driver.MongoQueryParser; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class MongoQueryParserTest +{ +// private final String sql = "SELECT name, age FROM users WHERE age > 18 AND city = 'Beijing' ORDER BY age DESC LIMIT 10"; + private final String sql = "SELECT hostname, startTime FROM startup_log"; + private MongoQueryParser parser; + + @Before + public void before() + { + this.parser = new MongoQueryParser(sql); + } + + @Test + public void testSelect() + { + System.out.println("Collection: " + parser.getCollection()); // users + System.out.println("Query: " + parser.getQuery()); // {age: {$gt: 18}, city: "Beijing"} + System.out.println("Sort: " + parser.getSort()); // {age: -1} + System.out.println("Limit: " + parser.getLimit()); // 10 + + assertEquals("users", parser.getCollection()); + assertEquals("{\"age\": {\"$gt\": 18}, \"city\": \"Beijing\"}", parser.getQuery().toJson()); + assertEquals("{\"age\": -1}", parser.getSort().toJson()); + assertEquals(10, parser.getLimit()); + } +} diff --git a/test/datacap-test-parser/pom.xml b/test/datacap-test-parser/pom.xml new file mode 100644 index 0000000000..cb6aa842ac --- /dev/null +++ b/test/datacap-test-parser/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + io.edurt.datacap + datacap + 2024.4.1-SNAPSHOT + ../../pom.xml + + + datacap-test-parser + DataCap - Test - Parser + + + + io.edurt.datacap + datacap-parser + test + + + diff --git a/test/datacap-test-parser/src/test/java/io/edurt/datacap/test/basic/SelectStatementTest.java b/test/datacap-test-parser/src/test/java/io/edurt/datacap/test/basic/SelectStatementTest.java new file mode 100644 index 0000000000..b0ea5a3f9a --- /dev/null +++ b/test/datacap-test-parser/src/test/java/io/edurt/datacap/test/basic/SelectStatementTest.java @@ -0,0 +1,153 @@ +package io.edurt.datacap.test.basic; + +import io.edurt.datacap.sql.SQLParser; +import io.edurt.datacap.sql.node.Expression; +import io.edurt.datacap.sql.node.clause.JoinClause; +import io.edurt.datacap.sql.node.element.OrderByElement; +import io.edurt.datacap.sql.node.element.SelectElement; +import io.edurt.datacap.sql.node.element.TableElement; +import io.edurt.datacap.sql.statement.SQLStatement; +import io.edurt.datacap.sql.statement.SelectStatement; +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class SelectStatementTest +{ + @Test + public void testSimpleSelect() + { + String sql = "SELECT id, name FROM users"; + SQLStatement stmt = SQLParser.parse(sql); + + assertTrue(stmt instanceof SelectStatement); + SelectStatement select = (SelectStatement) stmt; + + List selectElements = select.getSelectElements(); + assertEquals(2, selectElements.size()); + assertEquals("id", selectElements.get(0).getColumn()); + assertEquals("name", selectElements.get(1).getColumn()); + + List fromSources = select.getFromSources(); + assertEquals(1, fromSources.size()); + assertEquals("users", fromSources.get(0).getTableName()); + } + + @Test + public void testSelectWithWhereAndOrderBy() + { + String sql = "SELECT id, name FROM users WHERE age > 18 ORDER BY name DESC"; + SelectStatement select = (SelectStatement) SQLParser.parse(sql); + + Expression where = select.getWhereClause(); + assertNotNull(where); + assertEquals(Expression.ExpressionType.BINARY_OP, where.getType()); + + List orderBy = select.getOrderByElements(); + assertEquals(1, orderBy.size()); + assertFalse(orderBy.get(0).isAscending()); + } + + @Test + public void testSelectWithJoin() + { + String sql = "SELECT u.id, u.name, o.order_id " + + "FROM users u " + + "LEFT JOIN orders o ON u.id = o.user_id"; + SelectStatement select = (SelectStatement) SQLParser.parse(sql); + + List fromSources = select.getFromSources(); + assertEquals(1, fromSources.size()); + TableElement mainTable = fromSources.get(0); + assertEquals("users", mainTable.getTableName()); + assertEquals("u", mainTable.getAlias()); + + List joins = mainTable.getJoins(); + assertEquals(1, joins.size()); + JoinClause join = joins.get(0); + assertEquals(JoinClause.JoinType.LEFT, join.getJoinType()); + assertEquals("orders", join.getRightTable().getTableName()); + assertEquals("o", join.getRightTable().getAlias()); + } + + @Test + public void testComplexSelect() + { + String sql = "SELECT " + + " u.id, " + + " u.name, " + + " COUNT(o.order_id) as order_count " + + "FROM users u " + + "LEFT JOIN orders o ON u.id = o.user_id " + + "WHERE u.status = 'active' " + + "GROUP BY u.id, u.name " + + "HAVING COUNT(o.order_id) > 5 " + + "ORDER BY order_count DESC " + + "LIMIT 10"; + + SelectStatement select = (SelectStatement) SQLParser.parse(sql); + + List selectElements = select.getSelectElements(); + assertEquals(3, selectElements.size()); + assertEquals("order_count", selectElements.get(2).getAlias()); + + List groupBy = select.getGroupByElements(); + assertEquals(2, groupBy.size()); + + Expression having = select.getHavingClause(); + assertNotNull(having); + + assertNotNull(select.getLimitClause()); + assertEquals(10, select.getLimitClause().getLimit()); + } + + @Test + public void testSelectWithSubquery() + { + String sql = "SELECT * FROM (SELECT id, name FROM users) as u"; + SelectStatement select = (SelectStatement) SQLParser.parse(sql); + + List fromSources = select.getFromSources(); + assertNotNull("FromSources should not be null", fromSources); + assertEquals("Should have one source", 1, fromSources.size()); + + TableElement table = fromSources.get(0); + assertNotNull("Table should not be null", table); + assertEquals("Alias should be 'u'", "u", table.getAlias()); + + SelectStatement subquery = table.getSubquery(); + assertNotNull("Subquery should not be null", subquery); + + List subqueryElements = subquery.getSelectElements(); + assertEquals("Subquery should have 2 columns", 2, subqueryElements.size()); + assertEquals("First column should be 'id'", "id", subqueryElements.get(0).getColumn()); + assertEquals("Second column should be 'name'", "name", subqueryElements.get(1).getColumn()); + } + + @Test + public void testSelectWithCaseWhen() + { + String sql = "SELECT id, " + + "CASE WHEN age < 18 THEN 'minor' " + + " WHEN age < 60 THEN 'adult' " + + " ELSE 'senior' END as age_group " + + "FROM users"; + + SelectStatement select = (SelectStatement) SQLParser.parse(sql); + List selectElements = select.getSelectElements(); + assertEquals(2, selectElements.size()); + assertEquals("age_group", selectElements.get(1).getAlias()); + } + + @Test(expected = RuntimeException.class) + public void testInvalidSQL() + { + String sql = "SELECT * FORM users"; + SQLParser.parse(sql); + } +} From 22dcc34ad426fb7081f4aa6f31c3ecb74a181536 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Tue, 3 Dec 2024 19:43:54 +0800 Subject: [PATCH 04/17] feat(parser): optimize g4 expression structure --- .../io/edurt/datacap/sql/parser/SqlBase.g4 | 78 +++--- .../java/io/edurt/datacap/sql/SQLVisitor.java | 33 +-- .../io/edurt/datacap/sql/node/Expression.java | 2 + .../sql/processor/ExpressionProcessor.java | 93 ++++++ driver/datacap-driver-mongodb/pom.xml | 4 + .../datacap/driver/MongoQueryParser.java | 265 +++++++++--------- .../test/mongo/MongoQueryParserTest.java | 5 +- 7 files changed, 279 insertions(+), 201 deletions(-) create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/processor/ExpressionProcessor.java diff --git a/core/datacap-parser/src/main/antlr4/io/edurt/datacap/sql/parser/SqlBase.g4 b/core/datacap-parser/src/main/antlr4/io/edurt/datacap/sql/parser/SqlBase.g4 index ca8c6a19d0..bfd6b9bb85 100644 --- a/core/datacap-parser/src/main/antlr4/io/edurt/datacap/sql/parser/SqlBase.g4 +++ b/core/datacap-parser/src/main/antlr4/io/edurt/datacap/sql/parser/SqlBase.g4 @@ -384,7 +384,7 @@ joinTypeClause | LEFT OUTER? JOIN | RIGHT OUTER? JOIN | FULL OUTER? JOIN - | JOIN // 这代表默认的 INNER JOIN + | JOIN ; joinCondition @@ -394,30 +394,44 @@ joinCondition // Expressions expression - : primary - | expression IS NOT? NULL - | expression IS NOT? (TRUE | FALSE) - | NOT expression - | expression AND expression - | expression OR expression - | expression comparisonOperator expression - | expression NOT? BETWEEN expression AND expression - | expression NOT? IN ('(' expression (',' expression)* ')' | selectStatement) - | expression NOT? LIKE expression - | '(' expression ')' - | expression '+' expression - | expression '-' expression - | expression '*' expression - | expression '/' expression - | expression '%' expression - | '+' expression - | '-' expression - ; - -primary - : literal - | columnReference - | functionCall + : '(' expression ')' #ParenExpression + | primary #PrimaryExpression + | expression comparisonOperator expression #ComparisonExpression + | expression AND expression #AndExpression + | expression OR expression #OrExpression + | expression NOT? BETWEEN expression AND expression #BetweenExpression + | expression NOT? IN ('(' expression (',' expression)* ')') #InExpression + | expression IS NOT? NULL #IsNullExpression + | expression IS NOT? (TRUE | FALSE) #IsBooleanExpression + | NOT expression #NotExpression + | expression '+' expression #AddExpression + | expression '-' expression #SubtractExpression + | expression '*' expression #MultiplyExpression + | expression '/' expression #DivideExpression + ; + + primary + : literal #LiteralPrimary + | columnReference #ColumnReferencePrimary + | functionCall #FunctionCallPrimary + ; + + literal + : STRING + | INTEGER_VALUE + | DECIMAL_VALUE + | TRUE + | FALSE + | NULL + ; + + comparisonOperator + : '=' | '>' | '<' | '>=' | '<=' | '<>' | '!=' | '<=>' + ; + +expressionList + : '(' expression (',' expression)* ')' + | selectStatement ; columnReference @@ -430,23 +444,9 @@ functionCall | EXTRACT '(' identifier FROM expression ')' ; -comparisonOperator - : '=' | '>' | '<' | '>=' | '<=' | '<>' | '!=' | '<=>' - ; - // Common elements value: expression; -literal - : STRING - | INTEGER_VALUE - | DECIMAL_VALUE - | TRUE - | FALSE - | NULL - | CURRENT_TIMESTAMP - ; - defaultValue : literal | '(' expression ')' diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java index 558fe30d20..c57a4eaef9 100644 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java @@ -8,6 +8,7 @@ import io.edurt.datacap.sql.node.element.TableElement; import io.edurt.datacap.sql.parser.SqlBaseBaseVisitor; import io.edurt.datacap.sql.parser.SqlBaseParser; +import io.edurt.datacap.sql.processor.ExpressionProcessor; import io.edurt.datacap.sql.statement.SQLStatement; import io.edurt.datacap.sql.statement.SelectStatement; @@ -17,7 +18,6 @@ public class SQLVisitor extends SqlBaseBaseVisitor { - @Override public SQLStatement visitSingleStatement(SqlBaseParser.SingleStatementContext ctx) { @@ -322,35 +322,8 @@ else if (ctx.joinTypeClause().FULL() != null) { private Expression processExpression(SqlBaseParser.ExpressionContext ctx) { - Expression expr = new Expression(); - - if (ctx.primary() != null) { - if (ctx.primary().literal() != null) { - expr.setType(Expression.ExpressionType.LITERAL); - expr.setValue(ctx.primary().literal().getText()); - } - else if (ctx.primary().columnReference() != null) { - expr.setType(Expression.ExpressionType.COLUMN_REFERENCE); - expr.setValue(ctx.primary().columnReference().getText()); - } - else if (ctx.primary().functionCall() != null) { - expr.setType(Expression.ExpressionType.FUNCTION_CALL); - expr.setValue(ctx.primary().functionCall().getText()); - } - } - else { - expr.setType(Expression.ExpressionType.BINARY_OP); - List children = new ArrayList<>(); - - if (ctx.expression().size() > 1) { - for (SqlBaseParser.ExpressionContext childCtx : ctx.expression()) { - children.add(processExpression(childCtx)); - } - } - expr.setChildren(children); - } - - return expr; + ExpressionProcessor processor = new ExpressionProcessor(); + return processor.visit(ctx); } private List visitGroupByElements(SqlBaseParser.GroupByClauseContext ctx) diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/Expression.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/Expression.java index c9eb2c427c..2aca0a0fad 100644 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/Expression.java +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/Expression.java @@ -2,11 +2,13 @@ import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.util.List; @Getter @Setter +@ToString public class Expression { private ExpressionType type; diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/processor/ExpressionProcessor.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/processor/ExpressionProcessor.java new file mode 100644 index 0000000000..74cc895aae --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/processor/ExpressionProcessor.java @@ -0,0 +1,93 @@ +package io.edurt.datacap.sql.processor; + +import io.edurt.datacap.sql.node.Expression; +import io.edurt.datacap.sql.parser.SqlBaseBaseVisitor; +import io.edurt.datacap.sql.parser.SqlBaseParser; + +import java.util.ArrayList; +import java.util.List; + +public class ExpressionProcessor + extends SqlBaseBaseVisitor +{ + @Override + public Expression visitAndExpression(SqlBaseParser.AndExpressionContext ctx) + { + Expression expr = new Expression(); + expr.setType(Expression.ExpressionType.BINARY_OP); + expr.setValue("AND"); + + List children = new ArrayList<>(); + // 左表达式 + // Left expression + children.add(visit(ctx.expression(0))); + // 右表达式 + // Right expression + children.add(visit(ctx.expression(1))); + expr.setChildren(children); + + return expr; + } + + @Override + public Expression visitOrExpression(SqlBaseParser.OrExpressionContext ctx) + { + Expression expr = new Expression(); + expr.setType(Expression.ExpressionType.BINARY_OP); + expr.setValue("OR"); + + List children = new ArrayList<>(); + // 左表达式 + // Left expression + children.add(visit(ctx.expression(0))); + // 右表达式 + // Right expression + children.add(visit(ctx.expression(1))); + expr.setChildren(children); + + return expr; + } + + @Override + public Expression visitComparisonExpression(SqlBaseParser.ComparisonExpressionContext ctx) + { + Expression expr = new Expression(); + expr.setType(Expression.ExpressionType.BINARY_OP); + expr.setValue(ctx.comparisonOperator().getText()); + + List children = new ArrayList<>(); + // 左表达式 + // Left expression + children.add(visit(ctx.expression(0))); + // 右表达式 + // Right expression + children.add(visit(ctx.expression(1))); + expr.setChildren(children); + + return expr; + } + + @Override + public Expression visitColumnReferencePrimary(SqlBaseParser.ColumnReferencePrimaryContext ctx) + { + Expression expr = new Expression(); + expr.setType(Expression.ExpressionType.COLUMN_REFERENCE); + expr.setValue(ctx.columnReference().getText()); + return expr; + } + + @Override + public Expression visitLiteralPrimary(SqlBaseParser.LiteralPrimaryContext ctx) + { + Expression expr = new Expression(); + expr.setType(Expression.ExpressionType.LITERAL); + expr.setValue(ctx.literal().getText()); + return expr; + } + + @Override + public Expression visitParenExpression(SqlBaseParser.ParenExpressionContext ctx) + { + return visit(ctx.expression()); + } +} diff --git a/driver/datacap-driver-mongodb/pom.xml b/driver/datacap-driver-mongodb/pom.xml index 342e02ff1a..f7adf59e28 100644 --- a/driver/datacap-driver-mongodb/pom.xml +++ b/driver/datacap-driver-mongodb/pom.xml @@ -18,6 +18,10 @@ org.mongodb mongodb-driver-sync + + io.edurt.datacap + datacap-parser + ch.qos.logback logback-classic diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoQueryParser.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoQueryParser.java index 41b48a0992..8de94d72cb 100644 --- a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoQueryParser.java +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoQueryParser.java @@ -1,19 +1,23 @@ package io.edurt.datacap.driver; +import io.edurt.datacap.sql.SQLParser; +import io.edurt.datacap.sql.node.Expression; +import io.edurt.datacap.sql.node.clause.LimitClause; +import io.edurt.datacap.sql.node.element.OrderByElement; +import io.edurt.datacap.sql.node.element.SelectElement; +import io.edurt.datacap.sql.node.element.TableElement; +import io.edurt.datacap.sql.statement.SQLStatement; +import io.edurt.datacap.sql.statement.SelectStatement; import lombok.Getter; import org.bson.Document; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import java.util.regex.Matcher; import java.util.regex.Pattern; @Getter public class MongoQueryParser { - // Getters for parsed components - // 获取解析后的组件 private String collection; private Document query; private Document update; @@ -22,16 +26,6 @@ public class MongoQueryParser private int limit = -1; private int skip = -1; - // SQL keywords pattern - // SQL关键字匹配模式 - private static final Pattern SELECT_PATTERN = - Pattern.compile("SELECT\\s+(.+?)\\s+FROM\\s+(\\w+)\\s*(?:WHERE\\s+(.+?))?\\s*(?:ORDER\\s+BY\\s+(.+?))?\\s*(?:LIMIT\\s+(\\d+))?\\s*(?:OFFSET\\s+(\\d+))?\\s*$", - Pattern.CASE_INSENSITIVE); - - private static final Pattern UPDATE_PATTERN = - Pattern.compile("UPDATE\\s+(\\w+)\\s+SET\\s+(.+?)(?:\\s+WHERE\\s+(.+))?", - Pattern.CASE_INSENSITIVE); - // Constructor that parses SQL query // 构造函数,解析SQL查询 public MongoQueryParser(String sql) @@ -43,13 +37,10 @@ public MongoQueryParser(String sql) // 解析SQL语句 private void parseSql(String sql) { - sql = sql.trim(); + SQLStatement statement = SQLParser.parse(sql.trim()); - if (sql.toUpperCase().startsWith("SELECT")) { - parseSelectStatement(sql); - } - else if (sql.toUpperCase().startsWith("UPDATE")) { - parseUpdateStatement(sql); + if (statement instanceof SelectStatement) { + parseSelectStatement((SelectStatement) statement); } else { throw new IllegalArgumentException("Unsupported SQL operation: " + sql); @@ -58,149 +49,165 @@ else if (sql.toUpperCase().startsWith("UPDATE")) { // Parse SELECT statement // 解析SELECT语句 - private void parseSelectStatement(String sql) + private void parseSelectStatement(SelectStatement select) { - Matcher matcher = SELECT_PATTERN.matcher(sql); - if (!matcher.find()) { - throw new IllegalArgumentException("Invalid SELECT statement: " + sql); - } - // Parse fields // 解析字段 - String fieldsList = matcher.group(1); - this.fields = new ArrayList<>(); - if (!fieldsList.equals("*")) { - Arrays.stream(fieldsList.split(",")) - .map(String::trim) - .forEach(fields::add); - } + parseSelectElements(select.getSelectElements()); - // Get collection name - // 获取集合名称 - this.collection = matcher.group(2); + // Get collection name from FROM clause + // 从FROM子句获取集合名称 + parseFromClause(select.getFromSources()); // Parse WHERE clause // 解析WHERE子句 - String whereClause = matcher.group(3); - this.query = whereClause != null ? parseWhereClause(whereClause) : new Document(); + if (select.getWhereClause() != null) { + Object queryResult = parseExpression(select.getWhereClause()); + if (queryResult instanceof Document) { + this.query = (Document) queryResult; + } + else { + this.query = new Document("$eq", queryResult); + } + } + else { + this.query = new Document(); + } // Parse ORDER BY // 解析ORDER BY - String orderBy = matcher.group(4); - if (orderBy != null) { - this.sort = parseOrderBy(orderBy); + if (select.getOrderByElements() != null && !select.getOrderByElements().isEmpty()) { + this.sort = parseOrderByElements(select.getOrderByElements()); } // Parse LIMIT and OFFSET // 解析LIMIT和OFFSET - String limitStr = matcher.group(5); - if (limitStr != null) { - this.limit = Integer.parseInt(limitStr); - } - - String offsetStr = matcher.group(6); - if (offsetStr != null) { - this.skip = Integer.parseInt(offsetStr); + LimitClause limitClause = select.getLimitClause(); + if (limitClause != null) { + this.limit = (int) limitClause.getLimit(); + this.skip = (int) limitClause.getOffset(); } } - // Parse UPDATE statement - // 解析UPDATE语句 - private void parseUpdateStatement(String sql) + // Parse SELECT elements to field list + // 解析SELECT元素到字段列表 + private void parseSelectElements(List elements) { - Matcher matcher = UPDATE_PATTERN.matcher(sql); - if (!matcher.find()) { - throw new IllegalArgumentException("Invalid UPDATE statement: " + sql); + this.fields = new ArrayList<>(); + if (elements != null) { + for (SelectElement element : elements) { + if (element.getColumn() != null) { + fields.add(element.getColumn()); + } + else if (element.getExpression() != null) { + fields.add(parseExpression(element.getExpression()).toString()); + } + } } - - // Get collection name - // 获取集合名称 - this.collection = matcher.group(1); - - // Parse SET clause - // 解析SET子句 - String setClause = matcher.group(2); - this.update = parseSetClause(setClause); - - // Parse WHERE clause - // 解析WHERE子句 - String whereClause = matcher.group(3); - this.query = whereClause != null ? parseWhereClause(whereClause) : new Document(); } - // Parse WHERE clause to MongoDB query - // 解析WHERE子句转换为MongoDB查询 - private Document parseWhereClause(String whereClause) + // Parse FROM clause to get collection name + // 解析FROM子句获取集合名称 + private void parseFromClause(List fromSources) { - Document query = new Document(); - String[] conditions = whereClause.split("AND"); - - for (String condition : conditions) { - condition = condition.trim(); - - // Handle different operators - // 处理不同的操作符 - if (condition.contains("=")) { - String[] parts = condition.split("="); - query.put(parts[0].trim(), parseValue(parts[1].trim())); - } - else if (condition.contains(">")) { - String[] parts = condition.split(">"); - query.put(parts[0].trim(), new Document("$gt", parseValue(parts[1].trim()))); - } - else if (condition.contains("<")) { - String[] parts = condition.split("<"); - query.put(parts[0].trim(), new Document("$lt", parseValue(parts[1].trim()))); - } - else if (condition.toLowerCase().contains("like")) { - String[] parts = condition.split("LIKE", 2); - String pattern = parts[1].trim().replaceAll("%", ".*").replaceAll("'", ""); - query.put(parts[0].trim(), Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); + if (fromSources != null && !fromSources.isEmpty()) { + TableElement mainTable = fromSources.get(0); + this.collection = mainTable.getTableName(); + + // MongoDB doesn't support JOINs + // MongoDB不支持JOIN操作 + if (mainTable.getJoins() != null && !mainTable.getJoins().isEmpty()) { + throw new IllegalArgumentException("MongoDB does not support JOIN operations"); } } - - return query; } - // Parse SET clause for UPDATE statement - // 解析UPDATE语句的SET子句 - private Document parseSetClause(String setClause) + private Object parseExpression(Expression expr) { - Document updateDoc = new Document(); - Document setDoc = new Document(); - - String[] setPairs = setClause.split(","); - for (String setPair : setPairs) { - String[] parts = setPair.trim().split("="); - String field = parts[0].trim(); - Object value = parseValue(parts[1].trim()); - setDoc.put(field, value); + if (expr == null) { + return null; } - updateDoc.put("$set", setDoc); - return updateDoc; + switch (expr.getType()) { + case LITERAL: + return parseValue(expr.getValue().toString()); + + case COLUMN_REFERENCE: + return expr.getValue().toString(); + + case BINARY_OP: + String operator = expr.getValue().toString(); + List children = expr.getChildren(); + + // Handle logical operators (AND, OR) + if ("AND".equalsIgnoreCase(operator) || "OR".equalsIgnoreCase(operator)) { + List conditions = new ArrayList<>(); + for (Expression child : children) { + Object result = parseExpression(child); + if (result instanceof Document) { + conditions.add((Document) result); + } + } + return new Document(operator.equalsIgnoreCase("AND") ? "$and" : "$or", conditions); + } + + // Handle comparison operators + if (children != null && children.size() == 2) { + Expression left = children.get(0); + Expression right = children.get(1); + + String field = parseExpression(left).toString(); + Object value = parseExpression(right); + + Document condition = new Document(); + switch (operator) { + case "=": + condition.put(field, value); + break; + case ">": + condition.put(field, new Document("$gt", value)); + break; + case "<": + condition.put(field, new Document("$lt", value)); + break; + case ">=": + condition.put(field, new Document("$gte", value)); + break; + case "<=": + condition.put(field, new Document("$lte", value)); + break; + case "!=": + condition.put(field, new Document("$ne", value)); + break; + case "LIKE": + String pattern = value.toString().replace("%", ".*"); + condition.put(field, Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); + break; + case "IN": + condition.put(field, new Document("$in", value)); + break; + default: + throw new IllegalArgumentException("Unsupported operator: " + operator); + } + return condition; + } + + throw new IllegalArgumentException("Invalid binary expression structure"); + + default: + throw new IllegalArgumentException("Unsupported expression type: " + expr.getType()); + } } - // Parse ORDER BY clause - // 解析ORDER BY子句 - private Document parseOrderBy(String orderByClause) + // Parse ORDER BY elements to MongoDB sort document + // 解析ORDER BY元素到MongoDB排序文档 + private Document parseOrderByElements(List elements) { Document orderBy = new Document(); - String[] parts = orderByClause.split(","); - - for (String part : parts) { - part = part.trim(); - if (part.toUpperCase().endsWith("DESC")) { - String field = part.substring(0, part.length() - 4).trim(); - orderBy.put(field, -1); - } - else { - String field = part.toUpperCase().endsWith("ASC") ? - part.substring(0, part.length() - 3).trim() : part; - orderBy.put(field.trim(), 1); - } + for (OrderByElement element : elements) { + String field = element.getExpression().getValue().toString(); + orderBy.put(field, element.isAscending() ? 1 : -1); } - return orderBy; } diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoQueryParserTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoQueryParserTest.java index 80a0e85935..5f6096c5bc 100644 --- a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoQueryParserTest.java +++ b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoQueryParserTest.java @@ -8,8 +8,7 @@ public class MongoQueryParserTest { -// private final String sql = "SELECT name, age FROM users WHERE age > 18 AND city = 'Beijing' ORDER BY age DESC LIMIT 10"; - private final String sql = "SELECT hostname, startTime FROM startup_log"; + private final String sql = "SELECT name, age FROM users WHERE age > 18 AND city = 'Beijing' ORDER BY age DESC LIMIT 10"; private MongoQueryParser parser; @Before @@ -27,7 +26,7 @@ public void testSelect() System.out.println("Limit: " + parser.getLimit()); // 10 assertEquals("users", parser.getCollection()); - assertEquals("{\"age\": {\"$gt\": 18}, \"city\": \"Beijing\"}", parser.getQuery().toJson()); + assertEquals("{\"$and\": [{\"age\": {\"$gt\": 18}}, {\"city\": \"Beijing\"}]}", parser.getQuery().toJson()); assertEquals("{\"age\": -1}", parser.getSort().toJson()); assertEquals(10, parser.getLimit()); } From 504f2500ced42c6392df0aa706ae8a5fc3d08f30 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Tue, 3 Dec 2024 20:19:59 +0800 Subject: [PATCH 05/17] feat(parser): support show --- .../io/edurt/datacap/sql/parser/SqlBase.g4 | 34 ++++ .../java/io/edurt/datacap/sql/SQLVisitor.java | 11 ++ .../datacap/sql/processor/ShowProcessor.java | 87 +++++++++ .../datacap/sql/statement/SQLStatement.java | 2 +- .../datacap/sql/statement/ShowStatement.java | 29 +++ .../datacap/test/basic/ShowStatementTest.java | 177 ++++++++++++++++++ 6 files changed, 339 insertions(+), 1 deletion(-) create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/processor/ShowProcessor.java create mode 100644 core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/ShowStatement.java create mode 100644 test/datacap-test-parser/src/test/java/io/edurt/datacap/test/basic/ShowStatementTest.java diff --git a/core/datacap-parser/src/main/antlr4/io/edurt/datacap/sql/parser/SqlBase.g4 b/core/datacap-parser/src/main/antlr4/io/edurt/datacap/sql/parser/SqlBase.g4 index bfd6b9bb85..264114b73c 100644 --- a/core/datacap-parser/src/main/antlr4/io/edurt/datacap/sql/parser/SqlBase.g4 +++ b/core/datacap-parser/src/main/antlr4/io/edurt/datacap/sql/parser/SqlBase.g4 @@ -53,6 +53,12 @@ EXISTS: [Ee][Xx][Ii][Ss][Tt][Ss]; REPLACE: [Rr][Ee][Pp][Ll][Aa][Cc][Ee]; TEMP: [Tt][Ee][Mm][Pp]; TEMPORARY: [Tt][Ee][Mm][Pp][Oo][Rr][Aa][Rr][Yy]; +SHOW: [Ss][Hh][Oo][Ww]; +DATABASES: [Dd][Aa][Tt][Aa][Bb][Aa][Ss][Ee][Ss]; +TABLES: [Tt][Aa][Bb][Ll][Ee][Ss]; +COLUMNS: [Cc][Oo][Ll][Uu][Mm][Nn][Ss]; +CREATE_TIME: [Cc][Rr][Ee][Aa][Tt][Ee]'_'[Tt][Ii][Mm][Ee]; +UPDATE_TIME: [Uu][Pp][Dd][Aa][Tt][Ee]'_'[Tt][Ii][Mm][Ee]; // Operators AND: [Aa][Nn][Dd]; @@ -99,6 +105,7 @@ statement | alterStatement | dropStatement | useStatement + | showStatement ; // USE statement @@ -347,6 +354,30 @@ dropDatabaseStatement : DROP DATABASE (IF EXISTS)? databaseName ; +// SHOW statement +showStatement + : showDatabasesStatement + | showTablesStatement + | showColumnsStatement + ; + +showDatabasesStatement + : SHOW DATABASES (LIKE STRING)? + ; + +showTablesStatement + : SHOW TABLES + (FROM | IN)? databaseName? + (LIKE STRING | WHERE expression)? + ; + +showColumnsStatement + : SHOW COLUMNS + (FROM | IN) tableName + ((FROM | IN) databaseName)? + (LIKE STRING | WHERE expression)? + ; + // FROM clause and JOINs fromClause : FROM tableSource (',' tableSource)* @@ -401,6 +432,7 @@ expression | expression OR expression #OrExpression | expression NOT? BETWEEN expression AND expression #BetweenExpression | expression NOT? IN ('(' expression (',' expression)* ')') #InExpression + | expression NOT? LIKE expression #LikeExpression // 添加这一行 | expression IS NOT? NULL #IsNullExpression | expression IS NOT? (TRUE | FALSE) #IsBooleanExpression | NOT expression #NotExpression @@ -536,6 +568,8 @@ nonReservedWord | BOOLEAN | BOOL | BLOB | TEXT | JSON | XML | CHARSET | COLLATE | AUTO_INCREMENT | COMMENT | ADD | MODIFY | ENGINE + | DATABASES | TABLES | COLUMNS + | CREATE_TIME | UPDATE_TIME ; // Lexer rules diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java index c57a4eaef9..a93c7656b7 100644 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java @@ -9,6 +9,7 @@ import io.edurt.datacap.sql.parser.SqlBaseBaseVisitor; import io.edurt.datacap.sql.parser.SqlBaseParser; import io.edurt.datacap.sql.processor.ExpressionProcessor; +import io.edurt.datacap.sql.processor.ShowProcessor; import io.edurt.datacap.sql.statement.SQLStatement; import io.edurt.datacap.sql.statement.SelectStatement; @@ -51,6 +52,9 @@ else if (ctx.dropStatement() != null) { else if (ctx.useStatement() != null) { return visitUseStatement(ctx.useStatement()); } + else if (ctx.showStatement() != null) { + return visitShowStatement(ctx.showStatement()); + } return null; } @@ -173,6 +177,13 @@ public SQLStatement visitUseStatement(SqlBaseParser.UseStatementContext ctx) return null; } + @Override + public SQLStatement visitShowStatement(SqlBaseParser.ShowStatementContext ctx) + { + ShowProcessor processor = new ShowProcessor(); + return processor.process(ctx); + } + @Override public SQLStatement visitQuerySpecification(SqlBaseParser.QuerySpecificationContext ctx) { diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/processor/ShowProcessor.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/processor/ShowProcessor.java new file mode 100644 index 0000000000..3b336c67c4 --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/processor/ShowProcessor.java @@ -0,0 +1,87 @@ +package io.edurt.datacap.sql.processor; + +import io.edurt.datacap.sql.parser.SqlBaseParser; +import io.edurt.datacap.sql.statement.ShowStatement; + +public class ShowProcessor +{ + private final ExpressionProcessor expressionProcessor; + + public ShowProcessor() + { + this.expressionProcessor = new ExpressionProcessor(); + } + + public ShowStatement process(SqlBaseParser.ShowStatementContext ctx) + { + ShowStatement statement = new ShowStatement(); + + if (ctx.showDatabasesStatement() != null) { + processShowDatabases(statement, ctx.showDatabasesStatement()); + } + else if (ctx.showTablesStatement() != null) { + processShowTables(statement, ctx.showTablesStatement()); + } + else if (ctx.showColumnsStatement() != null) { + processShowColumns(statement, ctx.showColumnsStatement()); + } + + return statement; + } + + private void processShowDatabases(ShowStatement statement, + SqlBaseParser.ShowDatabasesStatementContext ctx) + { + statement.setShowType(ShowStatement.ShowType.DATABASES); + if (ctx.STRING() != null) { + // Remove quotes from the pattern string + String pattern = ctx.STRING().getText(); + pattern = pattern.substring(1, pattern.length() - 1); + statement.setPattern(pattern); + } + } + + private void processShowTables(ShowStatement statement, + SqlBaseParser.ShowTablesStatementContext ctx) + { + statement.setShowType(ShowStatement.ShowType.TABLES); + + if (ctx.databaseName() != null) { + statement.setDatabaseName(ctx.databaseName().getText()); + } + + if (ctx.STRING() != null) { + // Remove quotes from the pattern string + String pattern = ctx.STRING().getText(); + pattern = pattern.substring(1, pattern.length() - 1); + statement.setPattern(pattern); + } + else if (ctx.expression() != null) { + statement.setWhereCondition(expressionProcessor.visit(ctx.expression())); + } + } + + private void processShowColumns(ShowStatement statement, + SqlBaseParser.ShowColumnsStatementContext ctx) + { + statement.setShowType(ShowStatement.ShowType.COLUMNS); + + if (ctx.tableName() != null) { + statement.setTableName(ctx.tableName().getText()); + } + + if (ctx.databaseName() != null) { + statement.setDatabaseName(ctx.databaseName().getText()); + } + + if (ctx.STRING() != null) { + // Remove quotes from the pattern string + String pattern = ctx.STRING().getText(); + pattern = pattern.substring(1, pattern.length() - 1); + statement.setPattern(pattern); + } + else if (ctx.expression() != null) { + statement.setWhereCondition(expressionProcessor.visit(ctx.expression())); + } + } +} diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/SQLStatement.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/SQLStatement.java index 60eeb8c1a2..24bff1bc31 100644 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/SQLStatement.java +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/SQLStatement.java @@ -16,6 +16,6 @@ public StatementType getType() public enum StatementType { - SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, USE + SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, USE, SHOW } } diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/ShowStatement.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/ShowStatement.java new file mode 100644 index 0000000000..7a64517de6 --- /dev/null +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/statement/ShowStatement.java @@ -0,0 +1,29 @@ +package io.edurt.datacap.sql.statement; + +import io.edurt.datacap.sql.node.Expression; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ShowStatement + extends SQLStatement +{ + private ShowType showType; + private String databaseName; + private String tableName; + private String pattern; + private Expression whereCondition; + + public ShowStatement() + { + super(StatementType.SHOW); + } + + public enum ShowType + { + DATABASES, + TABLES, + COLUMNS + } +} diff --git a/test/datacap-test-parser/src/test/java/io/edurt/datacap/test/basic/ShowStatementTest.java b/test/datacap-test-parser/src/test/java/io/edurt/datacap/test/basic/ShowStatementTest.java new file mode 100644 index 0000000000..ff4391b615 --- /dev/null +++ b/test/datacap-test-parser/src/test/java/io/edurt/datacap/test/basic/ShowStatementTest.java @@ -0,0 +1,177 @@ +package io.edurt.datacap.test.basic; + +import io.edurt.datacap.sql.SQLParser; +import io.edurt.datacap.sql.statement.SQLStatement; +import io.edurt.datacap.sql.statement.ShowStatement; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class ShowStatementTest +{ + private ShowStatement parse(String sql) + { + SQLStatement stmt = SQLParser.parse(sql); + + assertTrue(stmt instanceof ShowStatement); + return (ShowStatement) stmt; + } + + @Test + public void testShowDatabases() + { + // Basic SHOW DATABASES + ShowStatement stmt = parse("SHOW DATABASES"); + assertEquals(ShowStatement.ShowType.DATABASES, stmt.getShowType()); + assertNull(stmt.getPattern()); + assertNull(stmt.getWhereCondition()); + + // SHOW DATABASES with LIKE pattern + stmt = parse("SHOW DATABASES LIKE '%test%'"); + assertEquals(ShowStatement.ShowType.DATABASES, stmt.getShowType()); + assertEquals("%test%", stmt.getPattern()); + assertNull(stmt.getWhereCondition()); + + // Case insensitivity test + stmt = parse("show DATABASES like '%TEST%'"); + assertEquals(ShowStatement.ShowType.DATABASES, stmt.getShowType()); + assertEquals("%TEST%", stmt.getPattern()); + } + + @Test + public void testShowTables() + { + // Basic SHOW TABLES + ShowStatement stmt = parse("SHOW TABLES"); + assertEquals(ShowStatement.ShowType.TABLES, stmt.getShowType()); + assertNull(stmt.getDatabaseName()); + assertNull(stmt.getPattern()); + assertNull(stmt.getWhereCondition()); + + // SHOW TABLES with database + stmt = parse("SHOW TABLES FROM mydb"); + assertEquals(ShowStatement.ShowType.TABLES, stmt.getShowType()); + assertEquals("mydb", stmt.getDatabaseName()); + + // SHOW TABLES with IN keyword + stmt = parse("SHOW TABLES IN mydb"); + assertEquals(ShowStatement.ShowType.TABLES, stmt.getShowType()); + assertEquals("mydb", stmt.getDatabaseName()); + + // SHOW TABLES with LIKE pattern + stmt = parse("SHOW TABLES FROM mydb LIKE '%user%'"); + assertEquals(ShowStatement.ShowType.TABLES, stmt.getShowType()); + assertEquals("mydb", stmt.getDatabaseName()); + assertEquals("%user%", stmt.getPattern()); + + // SHOW TABLES with WHERE clause + stmt = parse("SHOW TABLES FROM mydb WHERE Tables_in_mydb LIKE '%user%'"); + assertEquals(ShowStatement.ShowType.TABLES, stmt.getShowType()); + assertEquals("mydb", stmt.getDatabaseName()); + assertNotNull(stmt.getWhereCondition()); + } + + @Test + public void testShowColumns() + { + // Basic SHOW COLUMNS + ShowStatement stmt = parse("SHOW COLUMNS FROM users"); + assertEquals(ShowStatement.ShowType.COLUMNS, stmt.getShowType()); + assertEquals("users", stmt.getTableName()); + assertNull(stmt.getDatabaseName()); + assertNull(stmt.getPattern()); + + // SHOW COLUMNS with database + stmt = parse("SHOW COLUMNS FROM users FROM mydb"); + assertEquals(ShowStatement.ShowType.COLUMNS, stmt.getShowType()); + assertEquals("users", stmt.getTableName()); + assertEquals("mydb", stmt.getDatabaseName()); + + // Alternative syntax with IN + stmt = parse("SHOW COLUMNS FROM users IN mydb"); + assertEquals(ShowStatement.ShowType.COLUMNS, stmt.getShowType()); + assertEquals("users", stmt.getTableName()); + assertEquals("mydb", stmt.getDatabaseName()); + + // SHOW COLUMNS with LIKE pattern + stmt = parse("SHOW COLUMNS FROM users LIKE '%id%'"); + assertEquals(ShowStatement.ShowType.COLUMNS, stmt.getShowType()); + assertEquals("users", stmt.getTableName()); + assertEquals("%id%", stmt.getPattern()); + + // SHOW COLUMNS with WHERE clause + stmt = parse("SHOW COLUMNS FROM users WHERE Field LIKE '%id%'"); + assertEquals(ShowStatement.ShowType.COLUMNS, stmt.getShowType()); + assertEquals("users", stmt.getTableName()); + assertNotNull(stmt.getWhereCondition()); + + // Full syntax test + stmt = parse("SHOW COLUMNS FROM users IN mydb WHERE Field LIKE '%id%'"); + assertEquals(ShowStatement.ShowType.COLUMNS, stmt.getShowType()); + assertEquals("users", stmt.getTableName()); + assertEquals("mydb", stmt.getDatabaseName()); + assertNotNull(stmt.getWhereCondition()); + } + + @Test + public void testEdgeCases() + { + // Mixed case + ShowStatement stmt = parse("ShOw DaTaBaSeS LiKe '%test%'"); + assertEquals(ShowStatement.ShowType.DATABASES, stmt.getShowType()); + assertEquals("%test%", stmt.getPattern()); + + // Extra whitespace + stmt = parse("SHOW TABLES FROM mydb"); + assertEquals(ShowStatement.ShowType.TABLES, stmt.getShowType()); + assertEquals("mydb", stmt.getDatabaseName()); + + // Complex WHERE conditions + stmt = parse("SHOW COLUMNS FROM users WHERE Field LIKE '%id%' AND Type = 'int'"); + assertEquals(ShowStatement.ShowType.COLUMNS, stmt.getShowType()); + assertEquals("users", stmt.getTableName()); + assertNotNull(stmt.getWhereCondition()); + } + + @Test(expected = RuntimeException.class) + public void testInvalidSyntax() + { + // This should throw an exception + parse("SHOW INVALID"); + } + + @Test + public void testQuotedIdentifiers() + { + // Test with quoted database name + ShowStatement stmt = parse("SHOW TABLES FROM `my-db`"); + assertEquals(ShowStatement.ShowType.TABLES, stmt.getShowType()); + assertEquals("`my-db`", stmt.getDatabaseName()); + + // Test with quoted table name + stmt = parse("SHOW COLUMNS FROM `user-table`"); + assertEquals(ShowStatement.ShowType.COLUMNS, stmt.getShowType()); + assertEquals("`user-table`", stmt.getTableName()); + + // Test with both quoted + stmt = parse("SHOW COLUMNS FROM `user-table` IN `my-db`"); + assertEquals(ShowStatement.ShowType.COLUMNS, stmt.getShowType()); + assertEquals("`user-table`", stmt.getTableName()); + assertEquals("`my-db`", stmt.getDatabaseName()); + } + + @Test + public void testPatternQuotes() + { + // Test with single quotes + ShowStatement stmt = parse("SHOW DATABASES LIKE '%test%'"); + assertEquals("%test%", stmt.getPattern()); + + // Test with double quotes + stmt = parse("SHOW DATABASES LIKE \"%test%\""); + assertEquals("%test%", stmt.getPattern()); + } +} From a6af0d9153c698193985de1ce82aff3f60720cee Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Wed, 4 Dec 2024 00:04:39 +0800 Subject: [PATCH 06/17] feat(driver-mongodb): support select and show --- .../datacap/driver/InMemoryFindIterable.java | 274 ++++++++++++++++++ .../edurt/datacap/driver/MongoConnection.java | 11 +- .../edurt/datacap/driver/MongoResultSet.java | 15 +- .../edurt/datacap/driver/MongoStatement.java | 128 +++++++- .../datacap/driver/parser/MongoParser.java | 47 +++ .../MongoSelectParser.java} | 37 +-- .../driver/parser/MongoShowParser.java | 74 +++++ test/datacap-test-driver/pom.xml | 4 + .../test/mongo/MongoJdbcDriverTest.java | 124 +++++++- ...erTest.java => MongoSelectParserTest.java} | 13 +- .../test/mongo/MongoShowParserTest.java | 92 ++++++ .../src/test/resources/logback.xml | 12 + 12 files changed, 766 insertions(+), 65 deletions(-) create mode 100644 driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/InMemoryFindIterable.java create mode 100644 driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoParser.java rename driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/{MongoQueryParser.java => parser/MongoSelectParser.java} (88%) create mode 100644 driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoShowParser.java rename test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/{MongoQueryParserTest.java => MongoSelectParserTest.java} (55%) create mode 100644 test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoShowParserTest.java create mode 100644 test/datacap-test-driver/src/test/resources/logback.xml diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/InMemoryFindIterable.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/InMemoryFindIterable.java new file mode 100644 index 0000000000..59f9a750bb --- /dev/null +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/InMemoryFindIterable.java @@ -0,0 +1,274 @@ +package io.edurt.datacap.driver; + +import com.mongodb.CursorType; +import com.mongodb.ExplainVerbosity; +import com.mongodb.Function; +import com.mongodb.ServerAddress; +import com.mongodb.ServerCursor; +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoCursor; +import com.mongodb.client.MongoIterable; +import com.mongodb.client.model.Collation; +import org.bson.BsonValue; +import org.bson.Document; +import org.bson.conversions.Bson; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class InMemoryFindIterable + implements FindIterable +{ + private final List documents; + + public InMemoryFindIterable(List documents) + { + this.documents = documents; + } + + @Override + public MongoCursor iterator() + { + return new InMemoryMongoCursor(documents); + } + + @Override + public MongoCursor cursor() + { + return null; + } + + @Override + public Document first() + { + return documents.isEmpty() ? null : documents.get(0); + } + + @Override + public MongoIterable map(Function function) + { + return null; + } + + @Override + public > A into(A objects) + { + return null; + } + + @Override + public FindIterable filter(Bson filter) + { + return this; + } + + @Override + public FindIterable limit(int limit) + { + return this; + } + + @Override + public FindIterable skip(int skip) + { + return this; + } + + @Override + public FindIterable maxTime(long maxTime, TimeUnit timeUnit) + { + return this; + } + + @Override + public FindIterable maxAwaitTime(long l, TimeUnit timeUnit) + { + return null; + } + + @Override + public FindIterable projection(Bson bson) + { + return null; + } + + @Override + public FindIterable sort(Bson bson) + { + return null; + } + + @Override + public FindIterable noCursorTimeout(boolean b) + { + return null; + } + + @Override + public FindIterable oplogReplay(boolean b) + { + return null; + } + + @Override + public FindIterable partial(boolean b) + { + return null; + } + + @Override + public FindIterable cursorType(CursorType cursorType) + { + return null; + } + + @Override + public FindIterable batchSize(int batchSize) + { + return this; + } + + @Override + public FindIterable collation(Collation collation) + { + return null; + } + + @Override + public FindIterable comment(String s) + { + return null; + } + + @Override + public FindIterable comment(BsonValue bsonValue) + { + return null; + } + + @Override + public FindIterable hint(Bson bson) + { + return null; + } + + @Override + public FindIterable hintString(String s) + { + return null; + } + + @Override + public FindIterable let(Bson bson) + { + return null; + } + + @Override + public FindIterable max(Bson bson) + { + return null; + } + + @Override + public FindIterable min(Bson bson) + { + return null; + } + + @Override + public FindIterable returnKey(boolean b) + { + return null; + } + + @Override + public FindIterable showRecordId(boolean b) + { + return null; + } + + @Override + public FindIterable allowDiskUse(Boolean aBoolean) + { + return null; + } + + @Override + public Document explain() + { + return null; + } + + @Override + public Document explain(ExplainVerbosity explainVerbosity) + { + return null; + } + + @Override + public E explain(Class aClass) + { + return null; + } + + @Override + public E explain(Class aClass, ExplainVerbosity explainVerbosity) + { + return null; + } + + private static class InMemoryMongoCursor + implements MongoCursor + { + private final List documents; + private int position = 0; + + public InMemoryMongoCursor(List documents) + { + this.documents = documents; + } + + @Override + public void close() + { + } + + @Override + public boolean hasNext() + { + return position < documents.size(); + } + + @Override + public Document next() + { + return documents.get(position++); + } + + @Override + public int available() + { + return 0; + } + + @Override + public Document tryNext() + { + return hasNext() ? next() : null; + } + + @Override + public ServerCursor getServerCursor() + { + return null; + } + + @Override + public ServerAddress getServerAddress() + { + return null; + } + } +} diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoConnection.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoConnection.java index 8727d58c7b..fb23b62b44 100644 --- a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoConnection.java +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoConnection.java @@ -43,7 +43,7 @@ public MongoConnection(String url, Properties info) throws SQLException { try { - String databaseName = info.getProperty("authDatabase", "admin"); + String databaseName = info.getProperty("database", "admin"); // 如果URL中包含认证信息,直接使用URL创建客户端 // If the URL contains authentication information, create a client directly using the URL @@ -84,7 +84,8 @@ public MongoConnection(String url, Properties info) else { // 无认证信息,直接连接 // No authentication information, connect directly - this.mongoClient = MongoClients.create(url); + // Remove jdbc: + this.mongoClient = MongoClients.create(url.substring(5)); } } @@ -144,7 +145,6 @@ private void checkClosed() // 关闭连接 @Override public void close() - throws SQLException { if (!isClosed) { mongoClient.close(); @@ -471,4 +471,9 @@ public boolean isWrapperFor(Class iface) { return false; } + + public MongoClient getClient() + { + return mongoClient; + } } diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoResultSet.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoResultSet.java index ec688bdef0..78c7fd42db 100644 --- a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoResultSet.java +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoResultSet.java @@ -42,10 +42,15 @@ public MongoResultSet(FindIterable result) { this.cursor = result.iterator(); this.columnNames = new ArrayList<>(); + this.current = null; + + // 预处理第一个文档以获取列名 + // Preprocess the first document to get the column names if (cursor.hasNext()) { - Document first = cursor.next(); - columnNames.addAll(first.keySet()); - this.current = first; + Document first = result.limit(1).first(); + if (first != null) { + columnNames.addAll(first.keySet()); + } } } @@ -60,6 +65,7 @@ public boolean next() current = cursor.next(); return true; } + current = null; return false; } @@ -70,6 +76,9 @@ public String getString(String columnLabel) throws SQLException { checkClosed(); + if (current == null) { + throw new SQLException("No current row"); + } Object value = current.get(columnLabel); return value == null ? null : value.toString(); } diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoStatement.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoStatement.java index fe13ff449a..b1bb221a2c 100644 --- a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoStatement.java +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoStatement.java @@ -2,6 +2,9 @@ import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import io.edurt.datacap.driver.parser.MongoParser; +import io.edurt.datacap.driver.parser.MongoShowParser; import lombok.extern.slf4j.Slf4j; import org.bson.Document; @@ -10,6 +13,8 @@ import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; @Slf4j public class MongoStatement @@ -32,17 +37,28 @@ public ResultSet executeQuery(String sql) throws SQLException { checkClosed(); + try { // Parse SQL to MongoDB query // 将SQL解析为MongoDB查询 - MongoQueryParser parser = new MongoQueryParser(sql); + MongoParser parser = MongoParser.createParser(sql); + if (parser instanceof MongoShowParser) { + return executeShowStatement((MongoShowParser) parser); + } + String collectionName = parser.getCollection(); Document query = parser.getQuery(); log.debug("Executing query: {}", query); - MongoCollection collection = connection.getDatabase().getCollection(collectionName); - FindIterable result = collection.find(query); + String[] dbAndTb = parser.getCollection().split("\\."); + MongoDatabase db = connection.getDatabase(); + if (dbAndTb.length > 1) { + db = connection.getClient().getDatabase(dbAndTb[0]); + collectionName = dbAndTb[1]; + } + MongoCollection collection = db.getCollection(collectionName); + FindIterable result = collection.find(query); return new MongoResultSet(result); } catch (Exception e) { @@ -50,6 +66,110 @@ public ResultSet executeQuery(String sql) } } + private ResultSet executeShowStatement(MongoShowParser parser) + throws SQLException + { + try { + switch (parser.getShowType()) { + case DATABASES: + return handleShowDatabases(parser); + case TABLES: + return handleShowTables(parser); + case COLUMNS: + return handleShowColumns(parser); + default: + throw new SQLException("Unsupported SHOW command type"); + } + } + catch (Exception e) { + throw new SQLException("Failed to execute SHOW command", e); + } + } + + private ResultSet handleShowDatabases(MongoShowParser parser) + { + List docs = connection.getClient().listDatabaseNames() + .map(name -> new Document("name", name)) + .into(new ArrayList<>()); + return new MongoResultSet(new InMemoryFindIterable(docs)); + } + + private ResultSet handleShowTables(MongoShowParser parser) + { + MongoDatabase db = parser.getDatabase() != null ? + connection.getClient().getDatabase(parser.getDatabase()) : + connection.getDatabase(); + + List docs = db.listCollectionNames() + .map(name -> new Document("name", name)) + .into(new ArrayList<>()); + return new MongoResultSet(new InMemoryFindIterable(docs)); + } + + private ResultSet handleShowColumns(MongoShowParser parser) + { + String[] dbAndTb = parser.getCollection().split("\\."); + String database = parser.getDatabase(); + String table = parser.getCollection(); + if (database == null && dbAndTb.length == 2) { + database = dbAndTb[0]; + table = dbAndTb[1]; + } + + MongoDatabase db = connection.getClient().getDatabase(database); + + Document sample = db.getCollection(table) + .find() + .limit(1) + .first(); + + List docs = new ArrayList<>(); + if (sample != null) { + sample.keySet().forEach(field -> + docs.add(new Document("name", field)) + ); + } + + return new MongoResultSet(new InMemoryFindIterable(docs)); + } + + private boolean matchesPattern(String value, String pattern) + { + if (pattern == null) { + return true; + } + return value.matches(pattern.replace("%", ".*")); + } + + private String getMongoFieldType(Object value) + { + if (value == null) { + return "null"; + } + if (value instanceof String) { + return "string"; + } + if (value instanceof Integer) { + return "int"; + } + if (value instanceof Long) { + return "long"; + } + if (value instanceof Double) { + return "double"; + } + if (value instanceof Boolean) { + return "boolean"; + } + if (value instanceof Document) { + return "document"; + } + if (value instanceof List) { + return "array"; + } + return value.getClass().getSimpleName(); + } + // Execute update statement // 执行更新语句 @Override @@ -58,7 +178,7 @@ public int executeUpdate(String sql) { checkClosed(); try { - MongoQueryParser parser = new MongoQueryParser(sql); + MongoParser parser = MongoParser.createParser(sql); String collectionName = parser.getCollection(); Document update = parser.getUpdate(); diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoParser.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoParser.java new file mode 100644 index 0000000000..2957121c12 --- /dev/null +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoParser.java @@ -0,0 +1,47 @@ +package io.edurt.datacap.driver.parser; + +import io.edurt.datacap.sql.SQLParser; +import io.edurt.datacap.sql.statement.SQLStatement; +import io.edurt.datacap.sql.statement.SelectStatement; +import io.edurt.datacap.sql.statement.ShowStatement; +import lombok.Getter; +import lombok.Setter; +import org.bson.Document; + +import java.util.List; + +@Getter +public class MongoParser +{ + protected Document query; + protected Document update; + protected Document sort; + protected Document filter; + protected List fields; + protected String collection; + protected String command; + protected ShowStatement.ShowType showType; + protected int limit = -1; + protected int skip = -1; + + @Setter + protected String database; + + // Parse SQL statement + // 解析SQL语句 + public static MongoParser createParser(String sql) + { + if (sql == null || sql.trim().isEmpty()) { + throw new IllegalArgumentException("SQL query cannot be null or empty"); + } + + SQLStatement statement = SQLParser.parse(sql.trim()); + if (statement instanceof SelectStatement) { + return new MongoSelectParser((SelectStatement) statement); + } + else if (statement instanceof ShowStatement) { + return new MongoShowParser((ShowStatement) statement); + } + throw new IllegalArgumentException("Unsupported SQL operation: " + sql); + } +} diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoQueryParser.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoSelectParser.java similarity index 88% rename from driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoQueryParser.java rename to driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoSelectParser.java index 8de94d72cb..7829084f8b 100644 --- a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoQueryParser.java +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoSelectParser.java @@ -1,12 +1,10 @@ -package io.edurt.datacap.driver; +package io.edurt.datacap.driver.parser; -import io.edurt.datacap.sql.SQLParser; import io.edurt.datacap.sql.node.Expression; import io.edurt.datacap.sql.node.clause.LimitClause; import io.edurt.datacap.sql.node.element.OrderByElement; import io.edurt.datacap.sql.node.element.SelectElement; import io.edurt.datacap.sql.node.element.TableElement; -import io.edurt.datacap.sql.statement.SQLStatement; import io.edurt.datacap.sql.statement.SelectStatement; import lombok.Getter; import org.bson.Document; @@ -16,40 +14,17 @@ import java.util.regex.Pattern; @Getter -public class MongoQueryParser +public class MongoSelectParser + extends MongoParser { - private String collection; - private Document query; - private Document update; - private List fields; - private Document sort; - private int limit = -1; - private int skip = -1; - - // Constructor that parses SQL query - // 构造函数,解析SQL查询 - public MongoQueryParser(String sql) + public MongoSelectParser(SelectStatement statement) { - parseSql(sql); - } - - // Parse SQL statement - // 解析SQL语句 - private void parseSql(String sql) - { - SQLStatement statement = SQLParser.parse(sql.trim()); - - if (statement instanceof SelectStatement) { - parseSelectStatement((SelectStatement) statement); - } - else { - throw new IllegalArgumentException("Unsupported SQL operation: " + sql); - } + parseSelectStatement(statement); } // Parse SELECT statement // 解析SELECT语句 - private void parseSelectStatement(SelectStatement select) + public void parseSelectStatement(SelectStatement select) { // Parse fields // 解析字段 diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoShowParser.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoShowParser.java new file mode 100644 index 0000000000..e4620a444e --- /dev/null +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoShowParser.java @@ -0,0 +1,74 @@ +package io.edurt.datacap.driver.parser; + +import io.edurt.datacap.sql.statement.ShowStatement; +import lombok.Getter; +import org.bson.Document; + +@Getter +public class MongoShowParser + extends MongoParser +{ + public MongoShowParser(ShowStatement statement) + { + parseShowStatement(statement); + } + + public void parseShowStatement(ShowStatement show) + { + this.showType = show.getShowType(); + switch (show.getShowType()) { + case DATABASES: + this.command = "listDatabases"; + if (show.getPattern() != null) { + // Convert SQL LIKE pattern to MongoDB regex pattern + String pattern = convertLikeToRegex(show.getPattern()); + this.filter = new Document("name", new Document("$regex", pattern)); + } + break; + + case TABLES: + this.command = "listCollections"; + if (show.getDatabaseName() != null) { + this.database = show.getDatabaseName(); + } + if (show.getPattern() != null) { + String pattern = convertLikeToRegex(show.getPattern()); + this.filter = new Document("name", new Document("$regex", pattern)); + } + break; + + case COLUMNS: + this.command = "listFields"; + if (show.getDatabaseName() != null) { + this.database = show.getDatabaseName(); + } + if (show.getTableName() != null) { + this.collection = show.getTableName(); + } + if (show.getPattern() != null) { + String pattern = convertLikeToRegex(show.getPattern()); + this.filter = new Document("name", new Document("$regex", pattern)); + } + break; + + default: + throw new IllegalArgumentException("Unsupported SHOW type: " + show.getShowType()); + } + } + + private String convertLikeToRegex(String likePattern) + { + // Remove quotes if present + if (likePattern.startsWith("'") && likePattern.endsWith("'")) { + likePattern = likePattern.substring(1, likePattern.length() - 1); + } + else if (likePattern.startsWith("\"") && likePattern.endsWith("\"")) { + likePattern = likePattern.substring(1, likePattern.length() - 1); + } + + // Convert SQL LIKE pattern to MongoDB regex pattern + return likePattern + .replace("%", ".*") // % matches any sequence of characters + .replace("_", "."); // _ matches any single character + } +} diff --git a/test/datacap-test-driver/pom.xml b/test/datacap-test-driver/pom.xml index d4bba55d6f..bf88703bc7 100644 --- a/test/datacap-test-driver/pom.xml +++ b/test/datacap-test-driver/pom.xml @@ -19,5 +19,9 @@ ${project.version} test + + org.testcontainers + testcontainers + diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java index 8d029cfcde..ced0a9d7e5 100644 --- a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java +++ b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java @@ -1,40 +1,134 @@ package io.edurt.datacap.test.mongo; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoDatabase; +import org.bson.Document; +import org.junit.After; +import org.junit.Before; import org.junit.Test; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.time.Duration; +import java.util.List; import java.util.Properties; +import static org.junit.Assert.assertTrue; + public class MongoJdbcDriverTest { - @Test - public void test() + private Statement statement; + private GenericContainer container; + private Connection connection; + private MongoClient mongoClient; + + @Before + public void init() { - try - { - Class.forName("io.edurt.datacap.driver.MongoJdbcDriver"); + try { + container = new GenericContainer(DockerImageName.parse("mongo")) + .withExposedPorts(27017) + .withEnv("MONGO_INITDB_ROOT_USERNAME", "mongoadmin") + .withEnv("MONGO_INITDB_ROOT_PASSWORD", "secret") + .withCommand("mongod", "--noauth") + .waitingFor(Wait.forListeningPort() + .withStartupTimeout(Duration.ofSeconds(30))) + .withCommand("mongod", "--auth"); + container.setPortBindings(List.of("27017:27017")); + container.start(); + // Initialize test data using MongoDB Java Driver + String mongoUri = String.format("mongodb://mongoadmin:secret@%s:%d", + container.getHost(), + container.getFirstMappedPort()); + mongoClient = MongoClients.create(mongoUri); + MongoDatabase database = mongoClient.getDatabase("test"); + database.createCollection("sample"); + database.getCollection("sample").insertMany( + List.of( + new Document("name", "test1").append("value", 1), + new Document("name", "test2").append("value", 2) + ) + ); + + // Initialize JDBC connection + Class.forName("io.edurt.datacap.driver.MongoJdbcDriver"); Properties props = new Properties(); - props.setProperty("authDatabase", "admin"); + props.setProperty("database", "admin"); props.setProperty("user", "mongoadmin"); props.setProperty("password", "secret"); - props.setProperty("database", "local"); - Connection conn = DriverManager.getConnection("jdbc:mongodb://localhost:27017", props); - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT hostname, startTime FROM startup_log"); + String jdbcUrl = String.format("jdbc:mongodb://%s:%d", + container.getHost(), + container.getFirstMappedPort()); + + connection = DriverManager.getConnection(jdbcUrl, props); + statement = connection.createStatement(); + } + catch (Exception e) { + throw new RuntimeException("Failed to initialize test environment", e); + } + } + + @Test + public void testShow() + throws SQLException + { + try (ResultSet rs = statement.executeQuery("SHOW DATABASES")) { + assertTrue(rs.next()); + } + + try (ResultSet rs = statement.executeQuery("SHOW TABLES FROM test")) { + assertTrue(rs.next()); + } + + try (ResultSet rs = statement.executeQuery("SHOW COLUMNS FROM test.sample")) { + assertTrue(rs.next()); + } + } + + @Test + public void testSelect() + throws SQLException + { + try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample")) { + assertTrue(rs.next()); + } + + try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample WHERE value = 2")) { + assertTrue(rs.next()); + } + + try (ResultSet rs = statement.executeQuery("SELECT name FROM test.sample WHERE value = 2")) { + assertTrue(rs.next()); + } + } - while (rs.next()) - { - System.out.println(rs.getString("name")); + @After + public void cleanup() + { + try { + if (statement != null) { + statement.close(); + } + if (connection != null) { + connection.close(); + } + if (mongoClient != null) { + mongoClient.close(); + } + if (container != null) { + container.stop(); } } - catch (ClassNotFoundException | SQLException e) - { + catch (Exception e) { e.printStackTrace(); } } diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoQueryParserTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoSelectParserTest.java similarity index 55% rename from test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoQueryParserTest.java rename to test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoSelectParserTest.java index 5f6096c5bc..42eca59b14 100644 --- a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoQueryParserTest.java +++ b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoSelectParserTest.java @@ -1,30 +1,25 @@ package io.edurt.datacap.test.mongo; -import io.edurt.datacap.driver.MongoQueryParser; +import io.edurt.datacap.driver.parser.MongoParser; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; -public class MongoQueryParserTest +public class MongoSelectParserTest { private final String sql = "SELECT name, age FROM users WHERE age > 18 AND city = 'Beijing' ORDER BY age DESC LIMIT 10"; - private MongoQueryParser parser; + private MongoParser parser; @Before public void before() { - this.parser = new MongoQueryParser(sql); + this.parser = MongoParser.createParser(sql); } @Test public void testSelect() { - System.out.println("Collection: " + parser.getCollection()); // users - System.out.println("Query: " + parser.getQuery()); // {age: {$gt: 18}, city: "Beijing"} - System.out.println("Sort: " + parser.getSort()); // {age: -1} - System.out.println("Limit: " + parser.getLimit()); // 10 - assertEquals("users", parser.getCollection()); assertEquals("{\"$and\": [{\"age\": {\"$gt\": 18}}, {\"city\": \"Beijing\"}]}", parser.getQuery().toJson()); assertEquals("{\"age\": -1}", parser.getSort().toJson()); diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoShowParserTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoShowParserTest.java new file mode 100644 index 0000000000..cc912af0f8 --- /dev/null +++ b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoShowParserTest.java @@ -0,0 +1,92 @@ +package io.edurt.datacap.test.mongo; + +import io.edurt.datacap.driver.parser.MongoParser; +import io.edurt.datacap.sql.SQLParseException; +import org.bson.Document; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class MongoShowParserTest +{ + @Test + public void testShowDatabases() + { + // Basic SHOW DATABASES + MongoParser parser = MongoParser.createParser("SHOW DATABASES"); + assertEquals("listDatabases", parser.getCommand()); + assertNull(parser.getFilter()); + + // SHOW DATABASES with LIKE pattern + parser = MongoParser.createParser("SHOW DATABASES LIKE '%test%'"); + assertEquals("listDatabases", parser.getCommand()); + assertNotNull(parser.getFilter()); + Document filter = parser.getFilter(); + assertTrue(filter.containsKey("name")); + Document regex = (Document) filter.get("name"); + assertEquals(".*test.*", regex.get("$regex")); + } + + @Test + public void testShowTables() + { + // Basic SHOW TABLES + MongoParser parser = MongoParser.createParser("SHOW TABLES"); + assertEquals("listCollections", parser.getCommand()); + assertNull(parser.getDatabase()); + assertNull(parser.getFilter()); + + // SHOW TABLES FROM database + parser = MongoParser.createParser("SHOW TABLES FROM mydb"); + assertEquals("listCollections", parser.getCommand()); + assertEquals("mydb", parser.getDatabase()); + assertNull(parser.getFilter()); + + // SHOW TABLES with LIKE pattern + parser = MongoParser.createParser("SHOW TABLES FROM mydb LIKE '%user%'"); + assertEquals("listCollections", parser.getCommand()); + assertEquals("mydb", parser.getDatabase()); + assertNotNull(parser.getFilter()); + Document filter = parser.getFilter(); + assertTrue(filter.containsKey("name")); + Document regex = (Document) filter.get("name"); + assertEquals(".*user.*", regex.get("$regex")); + } + + @Test + public void testShowColumns() + { + // Basic SHOW COLUMNS + MongoParser parser = MongoParser.createParser("SHOW COLUMNS FROM users"); + assertEquals("listFields", parser.getCommand()); + assertEquals("users", parser.getCollection()); + assertNull(parser.getDatabase()); + assertNull(parser.getFilter()); + + // SHOW COLUMNS with database + parser = MongoParser.createParser("SHOW COLUMNS FROM users FROM mydb"); + assertEquals("listFields", parser.getCommand()); + assertEquals("users", parser.getCollection()); + assertEquals("mydb", parser.getDatabase()); + assertNull(parser.getFilter()); + + // SHOW COLUMNS with LIKE pattern + parser = MongoParser.createParser("SHOW COLUMNS FROM users LIKE '%id%'"); + assertEquals("listFields", parser.getCommand()); + assertEquals("users", parser.getCollection()); + assertNotNull(parser.getFilter()); + Document filter = parser.getFilter(); + assertTrue(filter.containsKey("name")); + Document regex = (Document) filter.get("name"); + assertEquals(".*id.*", regex.get("$regex")); + } + + @Test(expected = SQLParseException.class) + public void testInvalidStatement() + { + MongoParser.createParser("SHO"); + } +} diff --git a/test/datacap-test-driver/src/test/resources/logback.xml b/test/datacap-test-driver/src/test/resources/logback.xml new file mode 100644 index 0000000000..5d804bfa26 --- /dev/null +++ b/test/datacap-test-driver/src/test/resources/logback.xml @@ -0,0 +1,12 @@ + + + + + %date %level [%thread] %logger [%file:%line] %msg%n + + + + + + + From aed82d4245310c6b97dc04fc5245b13a798c0003 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Wed, 4 Dec 2024 11:55:07 +0800 Subject: [PATCH 07/17] feat(driver-mongodb): replace find to aggregate --- .../java/io/edurt/datacap/sql/SQLVisitor.java | 28 ++- .../io/edurt/datacap/sql/node/Expression.java | 2 +- .../sql/processor/ExpressionProcessor.java | 39 ++- .../driver/InMemoryAggregateIterable.java | 223 ++++++++++++++++++ .../edurt/datacap/driver/MongoResultSet.java | 8 +- .../edurt/datacap/driver/MongoStatement.java | 30 +-- .../datacap/driver/parser/MongoParser.java | 8 +- .../driver/parser/MongoSelectParser.java | 177 ++++++++++++-- test/datacap-test-driver/pom.xml | 9 +- .../test/mongo/MongoJdbcDriverTest.java | 41 +++- .../test/mongo/MongoSelectParserTest.java | 4 +- 11 files changed, 489 insertions(+), 80 deletions(-) create mode 100644 driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/InMemoryAggregateIterable.java diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java index a93c7656b7..a21a5cc672 100644 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/SQLVisitor.java @@ -217,17 +217,35 @@ private List processSelectElements(SqlBaseParser.SelectElementsCo SelectElement element = new SelectElement(); if (elementCtx.columnName() != null) { + // 直接指定的列名 + // Directly specified column names element.setColumn(elementCtx.columnName().getText()); } - + // 处理表达式 + // Handle expression + if (elementCtx.expression() != null) { + Expression expr = processExpression(elementCtx.expression()); + element.setExpression(expr); + + // 处理函数调用的情况 + // Handle function call + if (expr.getType() == Expression.ExpressionType.FUNCTION) { + // 尝试从函数的参数中获取列名 + // Try to get column name from function parameters + if (expr.getChildren() != null && !expr.getChildren().isEmpty()) { + Expression columnExpr = expr.getChildren().get(0); + if (columnExpr.getType() == Expression.ExpressionType.COLUMN_REFERENCE) { + element.setColumn(columnExpr.getValue().toString()); + } + } + } + } + // 处理别名 + // Handle alias if (elementCtx.alias() != null) { element.setAlias(elementCtx.alias().getText()); } - if (elementCtx.expression() != null) { - element.setExpression(processExpression(elementCtx.expression())); - } - elements.add(element); } diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/Expression.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/Expression.java index 2aca0a0fad..c703406f9e 100644 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/Expression.java +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/node/Expression.java @@ -17,6 +17,6 @@ public class Expression public enum ExpressionType { - LITERAL, COLUMN_REFERENCE, FUNCTION_CALL, BINARY_OP, UNARY_OP + LITERAL, COLUMN_REFERENCE, FUNCTION_CALL, BINARY_OP, UNARY_OP, FUNCTION } } diff --git a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/processor/ExpressionProcessor.java b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/processor/ExpressionProcessor.java index 74cc895aae..b04663ed4b 100644 --- a/core/datacap-parser/src/main/java/io/edurt/datacap/sql/processor/ExpressionProcessor.java +++ b/core/datacap-parser/src/main/java/io/edurt/datacap/sql/processor/ExpressionProcessor.java @@ -18,11 +18,7 @@ public Expression visitAndExpression(SqlBaseParser.AndExpressionContext ctx) expr.setValue("AND"); List children = new ArrayList<>(); - // 左表达式 - // Left expression children.add(visit(ctx.expression(0))); - // 右表达式 - // Right expression children.add(visit(ctx.expression(1))); expr.setChildren(children); @@ -37,11 +33,7 @@ public Expression visitOrExpression(SqlBaseParser.OrExpressionContext ctx) expr.setValue("OR"); List children = new ArrayList<>(); - // 左表达式 - // Left expression children.add(visit(ctx.expression(0))); - // 右表达式 - // Right expression children.add(visit(ctx.expression(1))); expr.setChildren(children); @@ -56,11 +48,7 @@ public Expression visitComparisonExpression(SqlBaseParser.ComparisonExpressionCo expr.setValue(ctx.comparisonOperator().getText()); List children = new ArrayList<>(); - // 左表达式 - // Left expression children.add(visit(ctx.expression(0))); - // 右表达式 - // Right expression children.add(visit(ctx.expression(1))); expr.setChildren(children); @@ -90,4 +78,31 @@ public Expression visitParenExpression(SqlBaseParser.ParenExpressionContext ctx) { return visit(ctx.expression()); } + + @Override + public Expression visitFunctionCallPrimary(SqlBaseParser.FunctionCallPrimaryContext ctx) + { + Expression expr = new Expression(); + expr.setType(Expression.ExpressionType.FUNCTION); + expr.setValue(ctx.functionCall().functionName().getText()); + + // 直接获取函数参数的文本表示,而不是创建子表达式 + // Directly get the text representation of function parameters, instead of creating child expressions + if (ctx.functionCall().expression() != null && !ctx.functionCall().expression().isEmpty()) { + SqlBaseParser.ExpressionContext firstArg = ctx.functionCall().expression(0); + String columnRef = firstArg.getText(); + + // 创建一个单独的 COLUMN_REFERENCE 表达式 + // Create a separate COLUMN_REFERENCE expression + Expression columnExpr = new Expression(); + columnExpr.setType(Expression.ExpressionType.COLUMN_REFERENCE); + columnExpr.setValue(columnRef); + + List args = new ArrayList<>(); + args.add(columnExpr); + expr.setChildren(args); + } + + return expr; + } } diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/InMemoryAggregateIterable.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/InMemoryAggregateIterable.java new file mode 100644 index 0000000000..f282fbc0ee --- /dev/null +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/InMemoryAggregateIterable.java @@ -0,0 +1,223 @@ +package io.edurt.datacap.driver; + +import com.mongodb.ExplainVerbosity; +import com.mongodb.Function; +import com.mongodb.ServerAddress; +import com.mongodb.ServerCursor; +import com.mongodb.client.AggregateIterable; +import com.mongodb.client.MongoCursor; +import com.mongodb.client.MongoIterable; +import com.mongodb.client.model.Collation; +import org.bson.BsonValue; +import org.bson.Document; +import org.bson.conversions.Bson; + +import java.util.Collection; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +public class InMemoryAggregateIterable + implements AggregateIterable +{ + private final List documents; + + public InMemoryAggregateIterable(List documents) + { + this.documents = documents; + } + + @Override + public MongoCursor iterator() + { + return new InMemoryMongoCursor(documents); + } + + @Override + public MongoCursor cursor() + { + return null; + } + + // Interface implementations with minimal implementation + @Override + public AggregateIterable batchSize(int size) + { + return this; + } + + @Override + public void toCollection() + {} + + @Override + public AggregateIterable allowDiskUse(Boolean allowDiskUse) + { + return this; + } + + @Override + public AggregateIterable maxTime(long maxTime, TimeUnit timeUnit) + { + return this; + } + + @Override + public AggregateIterable maxAwaitTime(long maxAwaitTime, TimeUnit timeUnit) + { + return this; + } + + @Override + public AggregateIterable bypassDocumentValidation(Boolean bypassDocumentValidation) + { + return this; + } + + @Override + public AggregateIterable collation(Collation collation) + { + return this; + } + + @Override + public AggregateIterable comment(String comment) + { + return this; + } + + @Override + public AggregateIterable comment(BsonValue bsonValue) + { + return null; + } + + @Override + public AggregateIterable hint(Bson hint) + { + return this; + } + + @Override + public AggregateIterable hintString(String s) + { + return null; + } + + @Override + public AggregateIterable let(Bson bson) + { + return null; + } + + @Override + public Document explain() + { + return null; + } + + @Override + public Document explain(ExplainVerbosity explainVerbosity) + { + return null; + } + + @Override + public E explain(Class aClass) + { + return null; + } + + @Override + public E explain(Class aClass, ExplainVerbosity explainVerbosity) + { + return null; + } + + @Override + public void forEach(Consumer action) + { + MongoCursor cursor = iterator(); + while (cursor.hasNext()) { + action.accept(cursor.next()); + } + } + + @Override + public > A into(A target) + { + forEach(target::add); + return target; + } + + @Override + public Document first() + { + MongoCursor cursor = iterator(); + return cursor.hasNext() ? cursor.next() : null; + } + + @Override + public MongoIterable map(Function mapper) + { + throw new UnsupportedOperationException("Map operation not supported"); + } + + private static class InMemoryMongoCursor + implements MongoCursor + { + private final List results; + private int position = 0; + + public InMemoryMongoCursor(List results) + { + this.results = results; + } + + @Override + public void close() + { + // No resources to close + } + + @Override + public boolean hasNext() + { + return position < results.size(); + } + + @Override + public Document next() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return results.get(position++); + } + + @Override + public int available() + { + return 0; + } + + @Override + public Document tryNext() + { + return hasNext() ? next() : null; + } + + @Override + public ServerCursor getServerCursor() + { + return null; + } + + @Override + public ServerAddress getServerAddress() + { + return null; + } + } +} diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoResultSet.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoResultSet.java index 78c7fd42db..cab6872e78 100644 --- a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoResultSet.java +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoResultSet.java @@ -1,6 +1,6 @@ package io.edurt.datacap.driver; -import com.mongodb.client.FindIterable; +import com.mongodb.client.AggregateIterable; import com.mongodb.client.MongoCursor; import org.bson.Document; @@ -38,7 +38,7 @@ public class MongoResultSet // Constructor // 构造函数 - public MongoResultSet(FindIterable result) + public MongoResultSet(AggregateIterable result) { this.cursor = result.iterator(); this.columnNames = new ArrayList<>(); @@ -47,7 +47,7 @@ public MongoResultSet(FindIterable result) // 预处理第一个文档以获取列名 // Preprocess the first document to get the column names if (cursor.hasNext()) { - Document first = result.limit(1).first(); + Document first = result.first(); if (first != null) { columnNames.addAll(first.keySet()); } @@ -61,6 +61,7 @@ public boolean next() throws SQLException { checkClosed(); + if (cursor.hasNext()) { current = cursor.next(); return true; @@ -76,6 +77,7 @@ public String getString(String columnLabel) throws SQLException { checkClosed(); + if (current == null) { throw new SQLException("No current row"); } diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoStatement.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoStatement.java index b1bb221a2c..7c44814960 100644 --- a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoStatement.java +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/MongoStatement.java @@ -1,6 +1,6 @@ package io.edurt.datacap.driver; -import com.mongodb.client.FindIterable; +import com.mongodb.client.AggregateIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import io.edurt.datacap.driver.parser.MongoParser; @@ -40,7 +40,6 @@ public ResultSet executeQuery(String sql) try { // Parse SQL to MongoDB query - // 将SQL解析为MongoDB查询 MongoParser parser = MongoParser.createParser(sql); if (parser instanceof MongoShowParser) { return executeShowStatement((MongoShowParser) parser); @@ -58,7 +57,12 @@ public ResultSet executeQuery(String sql) } MongoCollection collection = db.getCollection(collectionName); - FindIterable result = collection.find(query); + + // Execute aggregate command + @SuppressWarnings("unchecked") + List pipeline = (List) query.get("pipeline"); + AggregateIterable result = collection.aggregate(pipeline); + return new MongoResultSet(result); } catch (Exception e) { @@ -91,7 +95,7 @@ private ResultSet handleShowDatabases(MongoShowParser parser) List docs = connection.getClient().listDatabaseNames() .map(name -> new Document("name", name)) .into(new ArrayList<>()); - return new MongoResultSet(new InMemoryFindIterable(docs)); + return new MongoResultSet(new InMemoryAggregateIterable(docs)); } private ResultSet handleShowTables(MongoShowParser parser) @@ -103,7 +107,7 @@ private ResultSet handleShowTables(MongoShowParser parser) List docs = db.listCollectionNames() .map(name -> new Document("name", name)) .into(new ArrayList<>()); - return new MongoResultSet(new InMemoryFindIterable(docs)); + return new MongoResultSet(new InMemoryAggregateIterable(docs)); } private ResultSet handleShowColumns(MongoShowParser parser) @@ -129,8 +133,7 @@ private ResultSet handleShowColumns(MongoShowParser parser) docs.add(new Document("name", field)) ); } - - return new MongoResultSet(new InMemoryFindIterable(docs)); + return new MongoResultSet(new InMemoryAggregateIterable(docs)); } private boolean matchesPattern(String value, String pattern) @@ -176,18 +179,7 @@ private String getMongoFieldType(Object value) public int executeUpdate(String sql) throws SQLException { - checkClosed(); - try { - MongoParser parser = MongoParser.createParser(sql); - String collectionName = parser.getCollection(); - Document update = parser.getUpdate(); - - MongoCollection collection = connection.getDatabase().getCollection(collectionName); - return (int) collection.updateMany(parser.getQuery(), update).getModifiedCount(); - } - catch (Exception e) { - throw new SQLException("Failed to execute update", e); - } + throw new UnsupportedOperationException("Update operation not supported"); } // Check if statement is closed diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoParser.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoParser.java index 2957121c12..00343d3aff 100644 --- a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoParser.java +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoParser.java @@ -13,16 +13,12 @@ @Getter public class MongoParser { - protected Document query; - protected Document update; - protected Document sort; protected Document filter; protected List fields; - protected String collection; protected String command; + protected Document query; + protected String collection; protected ShowStatement.ShowType showType; - protected int limit = -1; - protected int skip = -1; @Setter protected String database; diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoSelectParser.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoSelectParser.java index 7829084f8b..e545c0f440 100644 --- a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoSelectParser.java +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoSelectParser.java @@ -10,13 +10,18 @@ import org.bson.Document; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.regex.Pattern; @Getter public class MongoSelectParser extends MongoParser { + private final Map fieldAliasMap = new HashMap<>(); + private final Map aliasToFieldMap = new HashMap<>(); + public MongoSelectParser(SelectStatement statement) { parseSelectStatement(statement); @@ -26,42 +31,73 @@ public MongoSelectParser(SelectStatement statement) // 解析SELECT语句 public void parseSelectStatement(SelectStatement select) { - // Parse fields - // 解析字段 + // Get collection name first + parseFromClause(select.getFromSources()); + + // Parse select elements to set fields parseSelectElements(select.getSelectElements()); - // Get collection name from FROM clause - // 从FROM子句获取集合名称 - parseFromClause(select.getFromSources()); + // Initialize an aggregation pipeline + List pipeline = new ArrayList<>(); - // Parse WHERE clause - // 解析WHERE子句 + // Add $match stage for WHERE conditions if (select.getWhereClause() != null) { Object queryResult = parseExpression(select.getWhereClause()); - if (queryResult instanceof Document) { - this.query = (Document) queryResult; - } - else { - this.query = new Document("$eq", queryResult); - } + Document matchStage = new Document("$match", + queryResult instanceof Document ? queryResult : new Document("$eq", queryResult)); + pipeline.add(matchStage); } - else { - this.query = new Document(); + + // Add $project stage for field selection + // Add $group stage if GROUP BY exists + if (select.getGroupByElements() != null && !select.getGroupByElements().isEmpty()) { + Document groupStage = parseGroupByClause(select.getGroupByElements(), select.getSelectElements()); + pipeline.add(new Document("$group", groupStage)); } + // If no GROUP BY, add normal $project stage + else if (fields != null && !fields.isEmpty() && + !(fields.size() == 1 && fields.get(0).equals("*"))) { + Document projectStage = new Document(); + projectStage.put("_id", 0); + + // Create field mappings in $project stage + for (SelectElement element : select.getSelectElements()) { + String originalField = element.getColumn() != null ? + element.getColumn() : + element.getExpression().getValue().toString(); - // Parse ORDER BY - // 解析ORDER BY + String alias = element.getAlias(); + if (alias != null) { + projectStage.put(alias, "$" + originalField); + } + else { + projectStage.put(originalField, 1); + } + } + pipeline.add(new Document("$project", projectStage)); + } + + // Add $sort stage if ORDER BY exists if (select.getOrderByElements() != null && !select.getOrderByElements().isEmpty()) { - this.sort = parseOrderByElements(select.getOrderByElements()); + Document sortStage = new Document("$sort", parseOrderByElements(select.getOrderByElements())); + pipeline.add(sortStage); } - // Parse LIMIT and OFFSET - // 解析LIMIT和OFFSET + // Add $skip and $limit stages if present LimitClause limitClause = select.getLimitClause(); if (limitClause != null) { - this.limit = (int) limitClause.getLimit(); - this.skip = (int) limitClause.getOffset(); + if (limitClause.getOffset() > 0) { + pipeline.add(new Document("$skip", (int) limitClause.getOffset())); + } + if (limitClause.getLimit() >= 0) { + pipeline.add(new Document("$limit", (int) limitClause.getLimit())); + } } + + // Set the final query + this.query = new Document("aggregate", this.collection) + .append("pipeline", pipeline) + .append("cursor", new Document()); } // Parse SELECT elements to field list @@ -71,11 +107,26 @@ private void parseSelectElements(List elements) this.fields = new ArrayList<>(); if (elements != null) { for (SelectElement element : elements) { + String field; + // Get field name (from column name or expression) if (element.getColumn() != null) { - fields.add(element.getColumn()); + field = element.getColumn(); } else if (element.getExpression() != null) { - fields.add(parseExpression(element.getExpression()).toString()); + field = parseExpression(element.getExpression()).toString(); + } + else { + continue; + } + + // Handle alias mapping + if (element.getAlias() != null) { + fieldAliasMap.put(field, element.getAlias()); + aliasToFieldMap.put(element.getAlias(), field); + fields.add(element.getAlias()); + } + else { + fields.add(field); } } } @@ -214,4 +265,82 @@ private Object parseValue(String value) return value; } } + + private Document parseGroupByClause(List groupByColumns, List selectElements) + { + Document groupStage = new Document(); + + // Handle _id field for grouping + if (groupByColumns.size() == 1 && groupByColumns.get(0).getValue().equals("_id")) { + groupStage.put("_id", "$" + groupByColumns.get(0).getValue()); + } + else { + // Multiple group by columns + Document idDoc = new Document(); + for (Expression expr : groupByColumns) { + String field = expr.getValue().toString(); + idDoc.put(field, "$" + field); + } + groupStage.put("_id", idDoc); + } + + // Handle aggregation functions in SELECT clause + for (SelectElement element : selectElements) { + if (element.getExpression() != null) { + Expression expr = element.getExpression(); + if (expr.getType() == Expression.ExpressionType.FUNCTION) { + String functionName = expr.getValue().toString().toUpperCase(); + String field = expr.getChildren().get(0).getValue().toString(); + String alias = element.getAlias() != null ? element.getAlias() : functionName + "_" + field; + + switch (functionName) { + case "COUNT": + if (field.equals("*")) { + groupStage.put(alias, new Document("$sum", 1)); + } + else { + groupStage.put(alias, new Document("$sum", 1)); + } + break; + case "SUM": + groupStage.put(alias, new Document("$sum", "$" + field)); + break; + case "AVG": + groupStage.put(alias, new Document("$avg", "$" + field)); + break; + case "MIN": + groupStage.put(alias, new Document("$min", "$" + field)); + break; + case "MAX": + groupStage.put(alias, new Document("$max", "$" + field)); + break; + default: + throw new IllegalArgumentException("Unsupported aggregation function: " + functionName); + } + } + else { + // Handle non-aggregated fields that are part of GROUP BY + String field = expr.getValue().toString(); + if (isFieldInGroupBy(field, groupByColumns)) { + groupStage.put(field, new Document("$first", "$" + field)); + } + } + } + else if (element.getColumn() != null) { + // Handle simple columns that are part of GROUP BY + String field = element.getColumn(); + if (isFieldInGroupBy(field, groupByColumns)) { + groupStage.put(field, new Document("$first", "$" + field)); + } + } + } + + return groupStage; + } + + private boolean isFieldInGroupBy(String field, List groupByColumns) + { + return groupByColumns.stream() + .anyMatch(expr -> expr.getValue().toString().equals(field)); + } } diff --git a/test/datacap-test-driver/pom.xml b/test/datacap-test-driver/pom.xml index bf88703bc7..143501ba26 100644 --- a/test/datacap-test-driver/pom.xml +++ b/test/datacap-test-driver/pom.xml @@ -7,21 +7,22 @@ io.edurt.datacap datacap 2024.4.1-SNAPSHOT + ../../pom.xml datacap-test-driver DataCap - Test - Driver + + org.testcontainers + testcontainers + io.edurt.datacap datacap-driver-mongodb ${project.version} test - - org.testcontainers - testcontainers - diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java index ced0a9d7e5..ba0480edf9 100644 --- a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java +++ b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java @@ -3,6 +3,7 @@ import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import com.mongodb.client.MongoDatabase; +import lombok.extern.slf4j.Slf4j; import org.bson.Document; import org.junit.After; import org.junit.Before; @@ -22,6 +23,7 @@ import static org.junit.Assert.assertTrue; +@Slf4j public class MongoJdbcDriverTest { private Statement statement; @@ -67,8 +69,8 @@ public void init() String jdbcUrl = String.format("jdbc:mongodb://%s:%d", container.getHost(), - container.getFirstMappedPort()); - + container.getFirstMappedPort() + ); connection = DriverManager.getConnection(jdbcUrl, props); statement = connection.createStatement(); } @@ -98,15 +100,48 @@ public void testShow() public void testSelect() throws SQLException { + log.info("Test simple select"); try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample")) { assertTrue(rs.next()); } + log.info("Test specific select column"); + try (ResultSet rs = statement.executeQuery("SELECT name FROM test.sample")) { + assertTrue(rs.next()); + } + + log.info("Test simple where clause"); try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample WHERE value = 2")) { assertTrue(rs.next()); } - try (ResultSet rs = statement.executeQuery("SELECT name FROM test.sample WHERE value = 2")) { + log.info("Test multiple where clause by and"); + try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample WHERE name = 'test1' AND value = 1")) { + assertTrue(rs.next()); + } + + log.info("Test multiple where clause by or"); + try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample WHERE name = 'test1' OR name = 'test2'")) { + assertTrue(rs.next()); + } + + log.info("Test order by"); + try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample ORDER BY name DESC, value DESC")) { + assertTrue(rs.next()); + } + + log.info("Test limit"); + try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample LIMIT 1")) { + assertTrue(rs.next()); + } + + log.info("Test group by"); + try (ResultSet rs = statement.executeQuery("SELECT name FROM test.sample GROUP BY name")) { + assertTrue(rs.next()); + } + + log.info("Test alias"); + try (ResultSet rs = statement.executeQuery("SELECT name as n, value as v FROM test.sample")) { assertTrue(rs.next()); } } diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoSelectParserTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoSelectParserTest.java index 42eca59b14..ae4f95eb62 100644 --- a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoSelectParserTest.java +++ b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoSelectParserTest.java @@ -21,8 +21,6 @@ public void before() public void testSelect() { assertEquals("users", parser.getCollection()); - assertEquals("{\"$and\": [{\"age\": {\"$gt\": 18}}, {\"city\": \"Beijing\"}]}", parser.getQuery().toJson()); - assertEquals("{\"age\": -1}", parser.getSort().toJson()); - assertEquals(10, parser.getLimit()); + assertEquals("{\"aggregate\": \"users\", \"pipeline\": [{\"$match\": {\"$and\": [{\"age\": {\"$gt\": 18}}, {\"city\": \"Beijing\"}]}}, {\"$project\": {\"_id\": 0, \"name\": 1, \"age\": 1}}, {\"$sort\": {\"age\": -1}}, {\"$limit\": 10}], \"cursor\": {}}", parser.getQuery().toJson()); } } From cc400dd2fcb26916d482f18095c9f41cf6f4f362 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Wed, 4 Dec 2024 12:08:39 +0800 Subject: [PATCH 08/17] feat(driver-mongodb): split tests --- .../datacap/test/mongo/MongoJdbcBaseTest.java | 115 ++++++++++++ .../mongo/MongoJdbcDriverAggregationTest.java | 44 +++++ .../test/mongo/MongoJdbcDriverSelectTest.java | 44 +++++ .../test/mongo/MongoJdbcDriverShowTest.java | 41 +++++ .../test/mongo/MongoJdbcDriverTest.java | 170 ------------------ .../test/mongo/MongoJdbcDriverWhereTest.java | 44 +++++ 6 files changed, 288 insertions(+), 170 deletions(-) create mode 100644 test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcBaseTest.java create mode 100644 test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverAggregationTest.java create mode 100644 test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverSelectTest.java create mode 100644 test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverShowTest.java delete mode 100644 test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java create mode 100644 test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverWhereTest.java diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcBaseTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcBaseTest.java new file mode 100644 index 0000000000..c639ed1452 --- /dev/null +++ b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcBaseTest.java @@ -0,0 +1,115 @@ +package io.edurt.datacap.test.mongo; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoDatabase; +import lombok.extern.slf4j.Slf4j; +import org.bson.Document; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.Statement; +import java.time.Duration; +import java.util.List; +import java.util.Properties; + +@Slf4j +public abstract class MongoJdbcBaseTest +{ + // Static container instance shared by all test classes + @ClassRule + public static final GenericContainer MONGO_CONTAINER = new GenericContainer(DockerImageName.parse("mongo")) + .withExposedPorts(27017) + .withEnv("MONGO_INITDB_ROOT_USERNAME", "mongoadmin") + .withEnv("MONGO_INITDB_ROOT_PASSWORD", "secret") + .withCommand("mongod", "--noauth") + .waitingFor(Wait.forListeningPort() + .withStartupTimeout(Duration.ofSeconds(30))) + .withCommand("mongod", "--auth"); + protected Statement statement; + protected Connection connection; + protected MongoClient mongoClient; + + @Before + public void init() + { + try { + initializeMongoData(); + initializeJdbcConnection(); + } + catch (Exception e) { + throw new RuntimeException("Failed to initialize test environment", e); + } + } + + private void initializeMongoData() + { + String mongoUri = String.format("mongodb://mongoadmin:secret@%s:%d", + MONGO_CONTAINER.getHost(), + MONGO_CONTAINER.getFirstMappedPort()); + mongoClient = MongoClients.create(mongoUri); + + // Clean up existing data + MongoDatabase database = mongoClient.getDatabase("test"); + try { + database.getCollection("sample").drop(); + } + catch (Exception ignored) { + } + + database.createCollection("sample"); + database.getCollection("sample").insertMany( + List.of( + new Document("name", "test1").append("value", 1), + new Document("name", "test2").append("value", 2) + ) + ); + } + + private void initializeJdbcConnection() + throws Exception + { + Class.forName("io.edurt.datacap.driver.MongoJdbcDriver"); + Properties props = new Properties(); + props.setProperty("database", "admin"); + props.setProperty("user", "mongoadmin"); + props.setProperty("password", "secret"); + + String jdbcUrl = String.format("jdbc:mongodb://%s:%d", + MONGO_CONTAINER.getHost(), + MONGO_CONTAINER.getFirstMappedPort() + ); + connection = DriverManager.getConnection(jdbcUrl, props); + statement = connection.createStatement(); + } + + @After + public void cleanup() + { + try { + if (statement != null) { + statement.close(); + } + if (connection != null) { + connection.close(); + } + if (mongoClient != null) { + mongoClient.close(); + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + + static { + MONGO_CONTAINER.setPortBindings(List.of("27017:27017")); + MONGO_CONTAINER.start(); + } +} diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverAggregationTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverAggregationTest.java new file mode 100644 index 0000000000..55e58b80d9 --- /dev/null +++ b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverAggregationTest.java @@ -0,0 +1,44 @@ +package io.edurt.datacap.test.mongo; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import static org.junit.Assert.assertTrue; + +@Slf4j +public class MongoJdbcDriverAggregationTest + extends MongoJdbcBaseTest +{ + @Test + public void testOrderBy() + throws SQLException + { + log.info("Test order by"); + try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample ORDER BY name DESC, value DESC")) { + assertTrue(rs.next()); + } + } + + @Test + public void testLimit() + throws SQLException + { + log.info("Test limit"); + try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample LIMIT 1")) { + assertTrue(rs.next()); + } + } + + @Test + public void testGroupBy() + throws SQLException + { + log.info("Test group by"); + try (ResultSet rs = statement.executeQuery("SELECT name FROM test.sample GROUP BY name")) { + assertTrue(rs.next()); + } + } +} diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverSelectTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverSelectTest.java new file mode 100644 index 0000000000..c2ec862dc9 --- /dev/null +++ b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverSelectTest.java @@ -0,0 +1,44 @@ +package io.edurt.datacap.test.mongo; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import static org.junit.Assert.assertTrue; + +@Slf4j +public class MongoJdbcDriverSelectTest + extends MongoJdbcBaseTest +{ + @Test + public void testSelectAll() + throws SQLException + { + log.info("Test simple select"); + try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample")) { + assertTrue(rs.next()); + } + } + + @Test + public void testSelectSpecificColumn() + throws SQLException + { + log.info("Test specific select column"); + try (ResultSet rs = statement.executeQuery("SELECT name FROM test.sample")) { + assertTrue(rs.next()); + } + } + + @Test + public void testSelectWithAlias() + throws SQLException + { + log.info("Test alias"); + try (ResultSet rs = statement.executeQuery("SELECT name as n, value as v FROM test.sample")) { + assertTrue(rs.next()); + } + } +} diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverShowTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverShowTest.java new file mode 100644 index 0000000000..863a4bfefc --- /dev/null +++ b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverShowTest.java @@ -0,0 +1,41 @@ +package io.edurt.datacap.test.mongo; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import static org.junit.Assert.assertTrue; + +@Slf4j +public class MongoJdbcDriverShowTest + extends MongoJdbcBaseTest +{ + @Test + public void testShowDatabases() + throws SQLException + { + try (ResultSet rs = statement.executeQuery("SHOW DATABASES")) { + assertTrue(rs.next()); + } + } + + @Test + public void testShowTables() + throws SQLException + { + try (ResultSet rs = statement.executeQuery("SHOW TABLES FROM test")) { + assertTrue(rs.next()); + } + } + + @Test + public void testShowColumns() + throws SQLException + { + try (ResultSet rs = statement.executeQuery("SHOW COLUMNS FROM test.sample")) { + assertTrue(rs.next()); + } + } +} diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java deleted file mode 100644 index ba0480edf9..0000000000 --- a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverTest.java +++ /dev/null @@ -1,170 +0,0 @@ -package io.edurt.datacap.test.mongo; - -import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; -import com.mongodb.client.MongoDatabase; -import lombok.extern.slf4j.Slf4j; -import org.bson.Document; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.wait.strategy.Wait; -import org.testcontainers.utility.DockerImageName; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.time.Duration; -import java.util.List; -import java.util.Properties; - -import static org.junit.Assert.assertTrue; - -@Slf4j -public class MongoJdbcDriverTest -{ - private Statement statement; - private GenericContainer container; - private Connection connection; - private MongoClient mongoClient; - - @Before - public void init() - { - try { - container = new GenericContainer(DockerImageName.parse("mongo")) - .withExposedPorts(27017) - .withEnv("MONGO_INITDB_ROOT_USERNAME", "mongoadmin") - .withEnv("MONGO_INITDB_ROOT_PASSWORD", "secret") - .withCommand("mongod", "--noauth") - .waitingFor(Wait.forListeningPort() - .withStartupTimeout(Duration.ofSeconds(30))) - .withCommand("mongod", "--auth"); - container.setPortBindings(List.of("27017:27017")); - container.start(); - - // Initialize test data using MongoDB Java Driver - String mongoUri = String.format("mongodb://mongoadmin:secret@%s:%d", - container.getHost(), - container.getFirstMappedPort()); - mongoClient = MongoClients.create(mongoUri); - MongoDatabase database = mongoClient.getDatabase("test"); - database.createCollection("sample"); - database.getCollection("sample").insertMany( - List.of( - new Document("name", "test1").append("value", 1), - new Document("name", "test2").append("value", 2) - ) - ); - - // Initialize JDBC connection - Class.forName("io.edurt.datacap.driver.MongoJdbcDriver"); - Properties props = new Properties(); - props.setProperty("database", "admin"); - props.setProperty("user", "mongoadmin"); - props.setProperty("password", "secret"); - - String jdbcUrl = String.format("jdbc:mongodb://%s:%d", - container.getHost(), - container.getFirstMappedPort() - ); - connection = DriverManager.getConnection(jdbcUrl, props); - statement = connection.createStatement(); - } - catch (Exception e) { - throw new RuntimeException("Failed to initialize test environment", e); - } - } - - @Test - public void testShow() - throws SQLException - { - try (ResultSet rs = statement.executeQuery("SHOW DATABASES")) { - assertTrue(rs.next()); - } - - try (ResultSet rs = statement.executeQuery("SHOW TABLES FROM test")) { - assertTrue(rs.next()); - } - - try (ResultSet rs = statement.executeQuery("SHOW COLUMNS FROM test.sample")) { - assertTrue(rs.next()); - } - } - - @Test - public void testSelect() - throws SQLException - { - log.info("Test simple select"); - try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample")) { - assertTrue(rs.next()); - } - - log.info("Test specific select column"); - try (ResultSet rs = statement.executeQuery("SELECT name FROM test.sample")) { - assertTrue(rs.next()); - } - - log.info("Test simple where clause"); - try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample WHERE value = 2")) { - assertTrue(rs.next()); - } - - log.info("Test multiple where clause by and"); - try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample WHERE name = 'test1' AND value = 1")) { - assertTrue(rs.next()); - } - - log.info("Test multiple where clause by or"); - try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample WHERE name = 'test1' OR name = 'test2'")) { - assertTrue(rs.next()); - } - - log.info("Test order by"); - try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample ORDER BY name DESC, value DESC")) { - assertTrue(rs.next()); - } - - log.info("Test limit"); - try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample LIMIT 1")) { - assertTrue(rs.next()); - } - - log.info("Test group by"); - try (ResultSet rs = statement.executeQuery("SELECT name FROM test.sample GROUP BY name")) { - assertTrue(rs.next()); - } - - log.info("Test alias"); - try (ResultSet rs = statement.executeQuery("SELECT name as n, value as v FROM test.sample")) { - assertTrue(rs.next()); - } - } - - @After - public void cleanup() - { - try { - if (statement != null) { - statement.close(); - } - if (connection != null) { - connection.close(); - } - if (mongoClient != null) { - mongoClient.close(); - } - if (container != null) { - container.stop(); - } - } - catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverWhereTest.java b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverWhereTest.java new file mode 100644 index 0000000000..db9cdf976f --- /dev/null +++ b/test/datacap-test-driver/src/test/java/io/edurt/datacap/test/mongo/MongoJdbcDriverWhereTest.java @@ -0,0 +1,44 @@ +package io.edurt.datacap.test.mongo; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import static org.junit.Assert.assertTrue; + +@Slf4j +public class MongoJdbcDriverWhereTest + extends MongoJdbcBaseTest +{ + @Test + public void testSimpleWhere() + throws SQLException + { + log.info("Test simple where clause"); + try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample WHERE value = 2")) { + assertTrue(rs.next()); + } + } + + @Test + public void testWhereWithAnd() + throws SQLException + { + log.info("Test multiple where clause by and"); + try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample WHERE name = 'test1' AND value = 1")) { + assertTrue(rs.next()); + } + } + + @Test + public void testWhereWithOr() + throws SQLException + { + log.info("Test multiple where clause by or"); + try (ResultSet rs = statement.executeQuery("SELECT * FROM test.sample WHERE name = 'test1' OR name = 'test2'")) { + assertTrue(rs.next()); + } + } +} From cb71becb9639dfe641f024a7730ff5cf48af4b45 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Wed, 4 Dec 2024 12:59:13 +0800 Subject: [PATCH 09/17] feat(driver-mongodb): add docs --- docs/docs/driver/mongodb.md | 96 +++++++++++++++++++ docs/mkdocs.yml | 4 + .../driver/parser/MongoSelectParser.java | 7 +- .../META-INF/services/java.sql.Driver | 1 + .../datacap/test/mongo/MongoJdbcBaseTest.java | 3 + .../mongo/MongoJdbcDriverAggregationTest.java | 20 ++++ 6 files changed, 125 insertions(+), 6 deletions(-) create mode 100644 docs/docs/driver/mongodb.md create mode 100644 driver/datacap-driver-mongodb/src/main/resources/META-INF/services/java.sql.Driver diff --git a/docs/docs/driver/mongodb.md b/docs/docs/driver/mongodb.md new file mode 100644 index 0000000000..d0f1d549a3 --- /dev/null +++ b/docs/docs/driver/mongodb.md @@ -0,0 +1,96 @@ +--- +title: MongoDB Driver +--- + +DataCap MongoDB Driver 主要要用于在 DataCap 中连接和操作 MongoDB 数据库。该驱动支持以下语法: + +- `SHOW ...` 语法 +- `SELECT ...` 语法 + +DataCap MongoDB Driver 适用于所有 DataCap 版本。 + +## 使用方式 + +--- + +```xml + + io.edurt.datacap + datacap-driver-mongodb + ${VERSION} + test + +``` + +`VERSION` 可以在 Maven 中央仓库中找到。 + +驱动名称:`io.edurt.datacap.driver.MongoJdbcDriver` + +支持的连接语法: + +- `jdbc:mongodb:` +- `jdbc:mongo:` +- `jdbc:mongodb+srv:` + +### 使用示例 + +- 授权用户 + +```java +Class.forName("io.edurt.datacap.driver.MongoJdbcDriver"); +Properties props = new Properties(); +props.setProperty("database", "xxxx"); +props.setProperty("user", "xxxx"); +props.setProperty("password", "xxxx"); + +String jdbcUrl = String.format("jdbc:mongodb://%s:%d", "127.0.0.1", 27017); +connection = DriverManager.getConnection(jdbcUrl, props); +``` + +- 非授权用户 + +```java +Class.forName("io.edurt.datacap.driver.MongoJdbcDriver"); +String jdbcUrl = String.format("jdbc:mongodb://%s:%d", "127.0.0.1", 27017); +connection = DriverManager.getConnection(jdbcUrl); +``` + +## SHOW 语法 + +DataCap MongoDB Driver 支持以下 SHOW 语法: + +- `SHOW DATABASES` +- `SHOW DATABASES LIKE ...` +- `SHOW TABLES` +- `SHOW TABLES FROM ...` +- `SHOW TABLES LIKE ...` +- `SHOW COLUMNS` +- `SHOW COLUMNS FROM ...` +- `SHOW COLUMNS FROM ... FROM ...` +- `SHOW COLUMNS FROM ... LIKE ...` + +## SELECT 语法 + +DataCap MongoDB Driver 支持以下 SELECT 语法: + +- `SELECT * FROM ...` +- `SELECT ... FROM ...` +- `SELECT column_name AS alias_name FROM ...` +- `SELECT column_name AS alias_name, ... FROM ...` +- `SELECT column_name AS alias_name, ... FROM ... WHERE ...` +- `SELECT column_name AS alias_name, ... FROM ... WHERE ... ORDER BY ...` +- `SELECT column_name AS alias_name, ... FROM ... WHERE ... ORDER BY ... LIMIT ...` +- `SELECT column_name AS alias_name, ... FROM ... WHERE ... GROUP BY ...` +- `SELECT column_name AS alias_name, ... FROM ... WHERE ... GROUP BY ... LIMIT ... OFFSET ...` +- `SELECT column_name AS alias_name, SUM(columnName) ... FROM ... WHERE ... GROUP BY ...` + +### 聚合函数 + +DataCap MongoDB Driver 支持以下聚合函数: + +- `COUNT(*)` +- `COUNT(columnName)` +- `SUM(columnName)` +- `AVG(columnName)` +- `MIN(columnName)` +- `MAX(columnName)` diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 1336cb210b..9bcf8f59cd 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -134,6 +134,7 @@ plugins: ApiPlugin: 插件 API ApiDashboard: 仪表盘 API ApiMenu: 菜单 API + NavDriver: 驱动 - locale: en name: English build: true @@ -158,6 +159,7 @@ plugins: ApiPlugin: Plugin API ApiDashboard: Dashboard API ApiMenu: Menu API + NavDriver: Driver - search - git-revision-date-localized: enable_creation_date: true @@ -309,5 +311,7 @@ nav: - api/menu/list.md - api/menu/save.md - api/menu/edit.md + - NavDriver: + - driver/mongodb.md - useCases.md - partners.md diff --git a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoSelectParser.java b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoSelectParser.java index e545c0f440..efdfcdf541 100644 --- a/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoSelectParser.java +++ b/driver/datacap-driver-mongodb/src/main/java/io/edurt/datacap/driver/parser/MongoSelectParser.java @@ -295,12 +295,7 @@ private Document parseGroupByClause(List groupByColumns, List