diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index eb5173e599e7d..cdd8b591d65c8 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -3,17 +3,23 @@ name: Mark stale issues and pull requests
on:
schedule:
- cron: '30 1 * * *'
+ workflow_dispatch:
+ inputs:
+ # https://github.com/marketplace/actions/close-stale-issues#operations-per-run
+ operationsPerRun:
+ description: 'Max number of operations per run'
+ required: true
+ default: 30
jobs:
stale:
-
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- - uses: actions/stale@v5
+ - uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: >
@@ -25,3 +31,6 @@ jobs:
stale-issue-label: 'no-issue-activity'
stale-pr-label: 'no-pr-activity'
days-before-close: -1
+ days-before-pr-close: 7
+ operations-per-run: ${{ github.event.inputs.operationsPerRun }}
+ enable-statistics: true
diff --git a/Cargo.lock b/Cargo.lock
index eb2ae2ed948cd..462b542829cee 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1097,6 +1097,19 @@ dependencies = [
"syn 2.0.57",
]
+[[package]]
+name = "asynchronous-codec"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4057f2c32adbb2fc158e22fb38433c8e9bbf76b75a4732c7c0cbaf695fb65568"
+dependencies = [
+ "bytes",
+ "futures-sink",
+ "futures-util",
+ "memchr",
+ "pin-project-lite",
+]
+
[[package]]
name = "atoi"
version = "2.0.0"
@@ -2654,6 +2667,12 @@ dependencies = [
"crossbeam-utils",
]
+[[package]]
+name = "connection-string"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "510ca239cf13b7f8d16a2b48f263de7b4f8c566f0af58d901031473c76afb1e3"
+
[[package]]
name = "console"
version = "0.15.7"
@@ -4540,6 +4559,70 @@ version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
+[[package]]
+name = "encoding"
+version = "0.2.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
+dependencies = [
+ "encoding-index-japanese",
+ "encoding-index-korean",
+ "encoding-index-simpchinese",
+ "encoding-index-singlebyte",
+ "encoding-index-tradchinese",
+]
+
+[[package]]
+name = "encoding-index-japanese"
+version = "1.20141219.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
+dependencies = [
+ "encoding_index_tests",
+]
+
+[[package]]
+name = "encoding-index-korean"
+version = "1.20141219.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
+dependencies = [
+ "encoding_index_tests",
+]
+
+[[package]]
+name = "encoding-index-simpchinese"
+version = "1.20141219.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
+dependencies = [
+ "encoding_index_tests",
+]
+
+[[package]]
+name = "encoding-index-singlebyte"
+version = "1.20141219.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
+dependencies = [
+ "encoding_index_tests",
+]
+
+[[package]]
+name = "encoding-index-tradchinese"
+version = "1.20141219.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
+dependencies = [
+ "encoding_index_tests",
+]
+
+[[package]]
+name = "encoding_index_tests"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
+
[[package]]
name = "encoding_rs"
version = "0.8.33"
@@ -8955,6 +9038,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04bfa62906ce8d9badf8d1764501640ae7f0bcea3437a209315830e0f73564d1"
+[[package]]
+name = "pretty-hex"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6fa0831dd7cc608c38a5e323422a0077678fa5744aa2be4ad91c4ece8eec8d5"
+
[[package]]
name = "pretty-xmlish"
version = "0.1.13"
@@ -10653,6 +10742,7 @@ dependencies = [
"tempfile",
"thiserror",
"thiserror-ext",
+ "tiberius",
"time",
"tokio-postgres",
"tokio-retry",
@@ -11066,14 +11156,25 @@ dependencies = [
name = "risingwave_java_binding"
version = "0.1.0"
dependencies = [
+ "anyhow",
+ "bytes",
+ "cfg-or-panic",
+ "foyer",
+ "futures",
"jni",
+ "madsim-tokio",
"prost 0.12.1",
"risingwave_common",
"risingwave_expr",
+ "risingwave_hummock_sdk",
"risingwave_jni_core",
+ "risingwave_object_store",
"risingwave_pb",
+ "risingwave_storage",
+ "rw_futures_util",
"serde",
"serde_json",
+ "tracing",
]
[[package]]
@@ -11096,9 +11197,7 @@ dependencies = [
"risingwave_common",
"risingwave_expr",
"risingwave_hummock_sdk",
- "risingwave_object_store",
"risingwave_pb",
- "risingwave_storage",
"rw_futures_util",
"serde",
"serde_json",
@@ -11991,6 +12090,18 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "rustls"
+version = "0.20.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99"
+dependencies = [
+ "log",
+ "ring 0.16.20",
+ "sct",
+ "webpki",
+]
+
[[package]]
name = "rustls"
version = "0.21.11"
@@ -14294,6 +14405,37 @@ dependencies = [
"ordered-float 2.10.0",
]
+[[package]]
+name = "tiberius"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc6e2bf3e4b5be181a2a2ceff4b9b12e2684010d436a6958bd564fbc8094d44d"
+dependencies = [
+ "async-trait",
+ "asynchronous-codec",
+ "bigdecimal 0.3.1",
+ "byteorder",
+ "bytes",
+ "chrono",
+ "connection-string",
+ "encoding",
+ "enumflags2",
+ "futures-util",
+ "num-traits",
+ "once_cell",
+ "pin-project-lite",
+ "pretty-hex",
+ "rust_decimal",
+ "rustls-native-certs 0.6.3",
+ "rustls-pemfile 1.0.4",
+ "thiserror",
+ "time",
+ "tokio-rustls 0.23.4",
+ "tokio-util",
+ "tracing",
+ "uuid",
+]
+
[[package]]
name = "tikv-jemalloc-ctl"
version = "0.5.4"
@@ -14497,6 +14639,17 @@ dependencies = [
"rand",
]
+[[package]]
+name = "tokio-rustls"
+version = "0.23.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
+dependencies = [
+ "rustls 0.20.9",
+ "tokio",
+ "webpki",
+]
+
[[package]]
name = "tokio-rustls"
version = "0.24.1"
@@ -14559,6 +14712,7 @@ checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d"
dependencies = [
"bytes",
"futures-core",
+ "futures-io",
"futures-sink",
"pin-project-lite",
"tokio",
@@ -15909,6 +16063,16 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "webpki"
+version = "0.22.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53"
+dependencies = [
+ "ring 0.17.5",
+ "untrusted 0.9.0",
+]
+
[[package]]
name = "webpki-roots"
version = "0.25.2"
diff --git a/Makefile.toml b/Makefile.toml
index a154f0ba60dba..1e618b1aed6ba 100644
--- a/Makefile.toml
+++ b/Makefile.toml
@@ -1417,7 +1417,7 @@ UPDATE_EXPECT=1 cargo test -p risingwave_connector tests::test_with_options_yaml
[tasks.backwards-compat-test]
category = "RiseDev - Test - Backwards Compatibility Test"
description = "Run backwards compatibility test"
-script = "./backwards-compat-tests/scripts/run_local.sh"
+script = "./e2e_test/backwards-compat-tests/scripts/run_local.sh"
# For debugging.
# To show the env for a specific task, use `run_task = "show-env"` for that task.
diff --git a/README.md b/README.md
index 47893c7bea1ba..156b53060313d 100644
--- a/README.md
+++ b/README.md
@@ -71,6 +71,9 @@ Then follow the prompts to start and connect to RisingWave.
To learn about other installation options, such as using a Docker image, see [Quick Start](https://docs.risingwave.com/docs/current/get-started/).
+> Please note: RisingWave uses [Scarf](https://scarf.sh/) to collect anonymized installation analytics. These analytics help support us understand and improve the distribution of our package.
+> The privacy policy of Scarf is available at [https://about.scarf.sh/privacy-policy](https://about.scarf.sh/privacy-policy).
+
## Production deployments
[**RisingWave Cloud**](https://cloud.risingwave.com) offers the easiest way to run RisingWave in production, with a _forever-free_ developer tier.
diff --git a/ci/docker-compose.yml b/ci/docker-compose.yml
index 4786f85327d14..b2a885a4ba2e6 100644
--- a/ci/docker-compose.yml
+++ b/ci/docker-compose.yml
@@ -1,4 +1,3 @@
-version: "3.9"
services:
db:
image: postgres:15-alpine
@@ -100,6 +99,7 @@ services:
- doris-server
- starrocks-fe-server
- starrocks-be-server
+ - sqlserver-server
volumes:
- ..:/risingwave
@@ -204,6 +204,16 @@ services:
timeout: 5s
retries: 30
+ sqlserver-server:
+ container_name: sqlserver-server
+ image: mcr.microsoft.com/mssql/server:2022-latest
+ hostname: sqlserver-server
+ ports:
+ - 1433:1433
+ environment:
+ ACCEPT_EULA: 'Y'
+ SA_PASSWORD: 'SomeTestOnly@SA'
+
starrocks-fe-server:
container_name: starrocks-fe-server
image: starrocks/fe-ubuntu:3.1.7
diff --git a/ci/scripts/backwards-compat-test.sh b/ci/scripts/backwards-compat-test.sh
index 9089be7a1bdc1..90a01f57a51cc 100755
--- a/ci/scripts/backwards-compat-test.sh
+++ b/ci/scripts/backwards-compat-test.sh
@@ -32,7 +32,7 @@ else
exit 1
fi
-source backwards-compat-tests/scripts/utils.sh
+source e2e_test/backwards-compat-tests/scripts/utils.sh
################################### Main
diff --git a/ci/scripts/e2e-sqlserver-sink-test.sh b/ci/scripts/e2e-sqlserver-sink-test.sh
new file mode 100755
index 0000000000000..f1f62941375ce
--- /dev/null
+++ b/ci/scripts/e2e-sqlserver-sink-test.sh
@@ -0,0 +1,80 @@
+#!/usr/bin/env bash
+
+# Exits as soon as any line fails.
+set -euo pipefail
+
+source ci/scripts/common.sh
+
+while getopts 'p:' opt; do
+ case ${opt} in
+ p )
+ profile=$OPTARG
+ ;;
+ \? )
+ echo "Invalid Option: -$OPTARG" 1>&2
+ exit 1
+ ;;
+ : )
+ echo "Invalid option: $OPTARG requires an argument" 1>&2
+ ;;
+ esac
+done
+shift $((OPTIND -1))
+
+download_and_prepare_rw "$profile" source
+
+echo "--- starting risingwave cluster"
+risedev ci-start ci-sink-test
+sleep 1
+
+echo "--- create SQL Server table"
+curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
+curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list
+apt-get update -y
+ACCEPT_EULA=Y DEBIAN_FRONTEND=noninteractive apt-get install -y mssql-tools unixodbc-dev
+export PATH="/opt/mssql-tools/bin/:$PATH"
+sleep 2
+
+sqlcmd -S sqlserver-server -U SA -P SomeTestOnly@SA -Q "
+CREATE DATABASE SinkTest;
+GO
+USE SinkTest;
+CREATE TABLE t_many_data_type (
+ k1 int, k2 int,
+ c_boolean bit,
+ c_int16 smallint,
+ c_int32 int,
+ c_int64 bigint,
+ c_float32 float,
+ c_float64 float,
+ c_decimal decimal,
+ c_date date,
+ c_time time,
+ c_timestamp datetime2,
+ c_timestampz datetime2,
+ c_nvarchar nvarchar(1024),
+ c_varbinary varbinary(1024),
+PRIMARY KEY (k1,k2));
+GO"
+sleep 2
+
+echo "--- testing sinks"
+sqllogictest -p 4566 -d dev './e2e_test/sink/sqlserver_sink.slt'
+sleep 1
+sqlcmd -S sqlserver-server -U SA -P SomeTestOnly@SA -h -1 -Q "
+SELECT * FROM SinkTest.dbo.t_many_data_type;
+GO" > ./query_result.txt
+
+mapfile -t actual < <(tr -s '[:space:]' '\n' < query_result.txt)
+actual=("${actual[@]:1}")
+expected=(0 0 0 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 1 1 0 55 55 1 1.0 1.0 1 2022-04-08 18:20:49.0000000 2022-03-13 01:00:00.0000000 2022-03-13 01:00:00.0000000 Hello World! 0xDE00BEEF 1 2 0 66 66 1 1.0 1.0 1 2022-04-08 18:20:49.0000000 2022-03-13 01:00:00.0000000 2022-03-13 01:00:00.0000000 Hello World! 0xDE00BEEF 1 4 0 2 2 1 1.0 1.0 1 2022-04-08 18:20:49.0000000 2022-03-13 01:00:00.0000000 2022-03-13 01:00:00.0000000 Hello World! 0xDE00BEEF "(4" rows "affected)")
+
+if [[ ${#actual[@]} -eq ${#expected[@]} && ${actual[@]} == ${expected[@]} ]]; then
+ echo "SQL Server sink check passed"
+else
+ cat ./query_result.txt
+ echo "The output is not as expected."
+fi
+
+echo "--- Kill cluster"
+risedev ci-kill
diff --git a/ci/scripts/run-backfill-tests.sh b/ci/scripts/run-backfill-tests.sh
index ac552cfcdcdd0..c03762a7150a7 100755
--- a/ci/scripts/run-backfill-tests.sh
+++ b/ci/scripts/run-backfill-tests.sh
@@ -185,6 +185,9 @@ test_sink_backfill_recovery() {
# Check progress
sqllogictest -p 4566 -d dev 'e2e_test/backfill/sink/create_sink.slt'
+ # Sleep before restart cluster, to ensure the downstream sink actually gets created.
+ sleep 5
+
# Restart
restart_cluster
sleep 5
diff --git a/ci/scripts/run-e2e-test.sh b/ci/scripts/run-e2e-test.sh
index 94398a77a8300..4736f4aa53a8a 100755
--- a/ci/scripts/run-e2e-test.sh
+++ b/ci/scripts/run-e2e-test.sh
@@ -92,7 +92,11 @@ sqllogictest -p 4566 -d dev './e2e_test/ddl/**/*.slt' --junit "batch-ddl-${profi
if [[ "$mode" != "single-node" ]]; then
sqllogictest -p 4566 -d dev './e2e_test/background_ddl/basic.slt' --junit "batch-ddl-${profile}"
fi
-sqllogictest -p 4566 -d dev './e2e_test/visibility_mode/*.slt' --junit "batch-${profile}"
+
+if [[ $mode != "single-node" ]]; then
+ sqllogictest -p 4566 -d dev './e2e_test/visibility_mode/*.slt' --junit "batch-${profile}"
+fi
+
sqllogictest -p 4566 -d dev './e2e_test/ttl/ttl.slt'
sqllogictest -p 4566 -d dev './e2e_test/database/prepare.slt'
sqllogictest -p 4566 -d test './e2e_test/database/test.slt'
diff --git a/ci/scripts/slow-e2e-test.sh b/ci/scripts/slow-e2e-test.sh
index 2fa1c977a9cfa..dc33c2719053b 100755
--- a/ci/scripts/slow-e2e-test.sh
+++ b/ci/scripts/slow-e2e-test.sh
@@ -36,5 +36,5 @@ echo "--- e2e, $mode, slow-udf-tests"
python3 -m pip install --break-system-packages arrow-udf==0.2.1
RUST_LOG="info" \
risedev ci-start "$mode"
-sqllogictest -p 4566 -d dev './e2e_test_slow/udf/always_retry_python.slt'
-sqllogictest -p 4566 -d dev './e2e_test_slow/backfill/rate_limit/slow-udf.slt'
+sqllogictest -p 4566 -d dev './e2e_test/slow_tests/udf/always_retry_python.slt'
+sqllogictest -p 4566 -d dev './e2e_test/slow_tests/backfill/rate_limit/slow-udf.slt'
diff --git a/ci/workflows/main-cron.yml b/ci/workflows/main-cron.yml
index 14f3a23161c80..c9eaf5cf0c38d 100644
--- a/ci/workflows/main-cron.yml
+++ b/ci/workflows/main-cron.yml
@@ -7,10 +7,6 @@ auto-retry: &auto-retry
steps:
- label: "build"
command: "ci/scripts/build.sh -p ci-release"
- if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
- || build.pull_request.labels includes "ci/run-build"
- || build.env("CI_STEPS") =~ /(^|,)build(,|$$)/
key: "build"
plugins:
- docker-compose#v5.1.0:
@@ -22,10 +18,6 @@ steps:
- label: "build other components"
command: "ci/scripts/build-other.sh"
- if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
- || build.pull_request.labels includes "ci/run-build-other"
- || build.env("CI_STEPS") =~ /(^|,)build-other(,|$$)/
key: "build-other"
plugins:
- seek-oss/aws-sm#v2.3.1:
@@ -42,10 +34,6 @@ steps:
- label: "build simulation test"
command: "ci/scripts/build-simulation.sh"
- if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
- || build.pull_request.labels includes "ci/run-build-simulation"
- || build.env("CI_STEPS") =~ /(^|,)build-simulation(,|$$)/
key: "build-simulation"
plugins:
- docker-compose#v5.1.0:
@@ -57,10 +45,6 @@ steps:
- label: "docslt"
command: "ci/scripts/docslt.sh"
- if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
- || build.pull_request.labels includes "ci/run-docslt"
- || build.env("CI_STEPS") =~ /(^|,)docslt(,|$$)/
key: "docslt"
plugins:
- docker-compose#v5.1.0:
@@ -74,7 +58,7 @@ steps:
key: "e2e-test-release"
command: "ci/scripts/cron-e2e-test.sh -p ci-release -m ci-3streaming-2serving-3fe"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-test"
|| build.env("CI_STEPS") =~ /(^|,)e2e-tests?(,|$$)/
depends_on:
@@ -94,7 +78,7 @@ steps:
key: "slow-e2e-test-release"
command: "ci/scripts/slow-e2e-test.sh -p ci-release -m ci-3streaming-2serving-3fe"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-slow-e2e-tests"
|| build.env("CI_STEPS") =~ /(^|,)slow-e2e-tests?(,|$$)/
depends_on:
@@ -113,7 +97,7 @@ steps:
key: "e2e-meta-backup-test-release"
command: "ci/scripts/run-meta-backup-test.sh -p ci-release -m ci-3streaming-2serving-3fe"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-meta-backup-test"
|| build.env("CI_STEPS") =~ /(^|,)e2e-tests?(,|$$)/
depends_on:
@@ -133,7 +117,7 @@ steps:
key: "e2e-test-release-parallel"
command: "ci/scripts/e2e-test-parallel.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-parallel-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-parallel-tests?(,|$$)/
depends_on:
@@ -158,7 +142,7 @@ steps:
key: "e2e-test-release-parallel-memory"
command: "ci/scripts/e2e-test-parallel-in-memory.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-parallel-in-memory-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-parallel-in-memory-tests?(,|$$)/
depends_on:
@@ -177,7 +161,7 @@ steps:
key: "e2e-test-release-source"
command: "ci/scripts/e2e-source-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-source-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-source-tests?(,|$$)/
depends_on:
@@ -196,7 +180,7 @@ steps:
key: "e2e-test-release-sink"
command: "ci/scripts/e2e-sink-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-sink-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-sink-tests?(,|$$)/
depends_on:
@@ -215,7 +199,7 @@ steps:
key: "fuzz-test"
command: "ci/scripts/cron-fuzz-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-sqlsmith-fuzzing-tests"
|| build.env("CI_STEPS") =~ /(^|,)sqlsmith-fuzzing-tests?(,|$$)/
depends_on:
@@ -237,7 +221,7 @@ steps:
key: "unit-test"
command: "ci/scripts/unit-test.sh"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-unit-test"
|| build.env("CI_STEPS") =~ /(^|,)unit-tests?(,|$$)/
plugins:
@@ -257,7 +241,7 @@ steps:
key: "unit-test-deterministic"
command: "MADSIM_TEST_NUM=100 timeout 30m ci/scripts/deterministic-unit-test.sh"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-unit-test-deterministic-simulation"
|| build.env("CI_STEPS") =~ /(^|,)unit-tests?-deterministic-simulation(,|$$)/
plugins:
@@ -272,7 +256,7 @@ steps:
key: "integration-test-deterministic-scale"
command: "TEST_NUM=60 ci/scripts/deterministic-it-test.sh scale::"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-integration-test-deterministic-simulation"
|| build.env("CI_STEPS") =~ /(^|,)integration-tests?-deterministic-simulation(,|$$)/
depends_on: "build-simulation"
@@ -289,7 +273,7 @@ steps:
key: "integration-test-deterministic-recovery"
command: "TEST_NUM=60 ci/scripts/deterministic-it-test.sh recovery::"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-integration-test-deterministic-simulation"
|| build.env("CI_STEPS") =~ /(^|,)integration-tests?-deterministic-simulation(,|$$)/
depends_on: "build-simulation"
@@ -306,7 +290,7 @@ steps:
key: "integration-test-deterministic-backfill"
command: "TEST_NUM=30 ci/scripts/deterministic-it-test.sh backfill_tests::"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-integration-test-deterministic-simulation"
|| build.env("CI_STEPS") =~ /(^|,)integration-tests?-deterministic-simulation(,|$$)/
depends_on: "build-simulation"
@@ -323,7 +307,7 @@ steps:
key: "integration-test-deterministic-storage"
command: "TEST_NUM=30 ci/scripts/deterministic-it-test.sh storage::"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-integration-test-deterministic-simulation"
|| build.env("CI_STEPS") =~ /(^|,)integration-tests?-deterministic-simulation(,|$$)/
depends_on: "build-simulation"
@@ -340,7 +324,7 @@ steps:
key: "integration-test-deterministic-sink"
command: "TEST_NUM=30 ci/scripts/deterministic-it-test.sh sink::"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-integration-test-deterministic-simulation"
|| build.env("CI_STEPS") =~ /(^|,)integration-tests?-deterministic-simulation(,|$$)/
depends_on: "build-simulation"
@@ -357,7 +341,7 @@ steps:
key: "e2e-test-deterministic"
command: "TEST_NUM=64 timeout 75m ci/scripts/deterministic-e2e-test.sh"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-test-deterministic-simulation"
|| build.env("CI_STEPS") =~ /(^|,)e2e-tests?-deterministic-simulation(,|$$)/
depends_on: "build-simulation"
@@ -379,7 +363,7 @@ steps:
key: "recovery-test-deterministic"
command: "TEST_NUM=12 KILL_RATE=1.0 BACKGROUND_DDL_RATE=0.0 timeout 65m ci/scripts/deterministic-recovery-test.sh"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-recovery-test-deterministic-simulation"
|| build.env("CI_STEPS") =~ /(^|,)recovery-tests?-deterministic-simulation(,|$$)/
depends_on: "build-simulation"
@@ -398,7 +382,7 @@ steps:
key: "background-ddl-arrangement-backfill-recovery-test-deterministic"
command: "TEST_NUM=12 KILL_RATE=1.0 BACKGROUND_DDL_RATE=0.8 USE_ARRANGEMENT_BACKFILL=--use-arrangement-backfill timeout 65m ci/scripts/deterministic-recovery-test.sh"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-recovery-test-deterministic-simulation"
|| build.env("CI_STEPS") =~ /(^|,)recovery-tests?-deterministic-simulation(,|$$)/
depends_on: "build-simulation"
@@ -416,7 +400,7 @@ steps:
key: "e2e-iceberg-sink-test"
command: "ci/scripts/e2e-iceberg-sink-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-iceberg-sink-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-iceberg-sink-tests?(,|$$)/
depends_on:
@@ -436,7 +420,7 @@ steps:
key: "e2e-iceberg-sink-v2-test"
command: "ci/scripts/e2e-iceberg-sink-v2-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-iceberg-sink-v2-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-iceberg-sink-v2-tests?(,|$$)/
depends_on:
@@ -455,7 +439,7 @@ steps:
key: "e2e-java-binding-tests"
command: "ci/scripts/java-binding-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-java-binding-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-java-binding-tests?(,|$$)/
depends_on:
@@ -476,7 +460,7 @@ steps:
key: "s3-v2-source-check-aws-json-parser"
command: "ci/scripts/s3-source-test.sh -p ci-release -s fs_source_v2.py -t json"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-s3-source-tests"
|| build.env("CI_STEPS") =~ /(^|,)s3-source-tests?(,|$$)/
depends_on: build
@@ -498,7 +482,7 @@ steps:
key: "s3-v2-source-batch-read-check-aws-json-parser"
command: "ci/scripts/s3-source-test.sh -p ci-release -s fs_source_batch.py -t json"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-s3-source-tests"
|| build.env("CI_STEPS") =~ /(^|,)s3-source-tests?(,|$$)/
depends_on: build
@@ -520,7 +504,7 @@ steps:
key: "s3-v2-source-check-aws-csv-parser"
command: "ci/scripts/s3-source-test.sh -p ci-release -s fs_source_v2.py -t csv_without_header"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-s3-source-tests"
|| build.env("CI_STEPS") =~ /(^|,)s3-source-tests?(,|$$)/
depends_on: build
@@ -542,7 +526,7 @@ steps:
key: "s3-source-test-for-opendal-fs-engine-csv-parser"
command: "ci/scripts/s3-source-test.sh -p ci-release -s posix_fs_source.py -t csv_without_header"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-s3-source-tests"
|| build.env("CI_STEPS") =~ /(^|,)s3-source-tests?(,|$$)/
depends_on: build
@@ -560,7 +544,7 @@ steps:
# key: "s3-source-test-for-opendal-fs-engine"
# command: "ci/scripts/s3-source-test-for-opendal-fs-engine.sh -p ci-release -s gcs_source.py"
# if: |
- # !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ # !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
# || build.pull_request.labels includes "ci/run-s3-source-tests"
# || build.env("CI_STEPS") =~ /(^|,)s3-source-tests?(,|$$)/
# depends_on: build
@@ -582,7 +566,7 @@ steps:
key: "pulsar-source-tests"
command: "ci/scripts/pulsar-source-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-pulsar-source-tests"
|| build.env("CI_STEPS") =~ /(^|,)pulsar-source-tests?(,|$$)/
depends_on:
@@ -607,7 +591,7 @@ steps:
key: "run-micro-benchmarks"
command: "ci/scripts/run-micro-benchmarks.sh"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-micro-benchmarks"
|| build.env("CI_STEPS") =~ /(^|,)micro-benchmarks?(,|$$)/
plugins:
@@ -622,7 +606,7 @@ steps:
key: "upload-micro-benchmarks"
if: |
build.branch == "main"
- || !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ || !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-micro-benchmarks"
|| build.env("CI_STEPS") =~ /(^|,)micro-benchmarks?(,|$$)/
command:
@@ -647,7 +631,7 @@ steps:
key: "backwards-compat-tests"
command: "VERSION_OFFSET={{matrix.version_offset}} RW_COMMIT=$BUILDKITE_COMMIT ci/scripts/backwards-compat-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-backwards-compat-tests"
|| build.env("CI_STEPS") =~ /(^|,)backwards?-compat-tests?(,|$$)/
depends_on:
@@ -681,7 +665,7 @@ steps:
key: "sqlsmith-differential-tests"
command: "ci/scripts/sqlsmith-differential-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-sqlsmith-differential-tests"
|| build.env("CI_STEPS") =~ /(^|,)sqlsmith-differential-tests?(,|$$)/
depends_on:
@@ -697,7 +681,7 @@ steps:
key: "backfill-tests"
command: "BUILDKITE=${BUILDKITE:-} ci/scripts/backfill-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-backfill-tests"
|| build.env("CI_STEPS") =~ /(^|,)backfill-tests?(,|$$)/
depends_on:
@@ -715,7 +699,7 @@ steps:
key: "e2e-standalone-binary-tests"
command: "ci/scripts/e2e-test.sh -p ci-release -m standalone"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-standalone-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-standalone-tests?(,|$$)/
depends_on:
@@ -735,7 +719,7 @@ steps:
key: "e2e-single-node-binary-tests"
command: "ci/scripts/e2e-test.sh -p ci-release -m single-node"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-single-node-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-single-node-tests?(,|$$)/
depends_on:
@@ -755,7 +739,7 @@ steps:
key: "e2e-test-opendal-parallel"
command: "ci/scripts/e2e-test-parallel-for-opendal.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-parallel-tests-for-opendal"
|| build.env("CI_STEPS") =~ /(^|,)e2e-parallel-tests?-for-opendal(,|$$)/
depends_on:
@@ -774,7 +758,7 @@ steps:
key: "e2e-deltalake-sink-rust-tests"
command: "ci/scripts/e2e-deltalake-sink-rust-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-deltalake-sink-rust-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-deltalake-sink-rust-tests?(,|$$)/
depends_on:
@@ -793,7 +777,7 @@ steps:
key: "e2e-redis-sink-tests"
command: "ci/scripts/e2e-redis-sink-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-redis-sink-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-redis-sink-tests?(,|$$)/
depends_on:
@@ -812,7 +796,7 @@ steps:
key: "e2e-doris-sink-tests"
command: "ci/scripts/e2e-doris-sink-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-doris-sink-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-doris-sink-tests?(,|$$)/
depends_on:
@@ -831,7 +815,7 @@ steps:
key: "e2e-starrocks-sink-tests"
command: "ci/scripts/e2e-starrocks-sink-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-starrocks-sink-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-starrocks-sink-tests?(,|$$)/
depends_on:
@@ -850,7 +834,7 @@ steps:
key: "e2e-cassandra-sink-tests"
command: "ci/scripts/e2e-cassandra-sink-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-cassandra-sink-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-cassandra-sink-tests?(,|$$)/
depends_on:
@@ -869,7 +853,7 @@ steps:
key: "e2e-clickhouse-sink-tests"
command: "ci/scripts/e2e-clickhouse-sink-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-clickhouse-sink-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-clickhouse-sink-tests?(,|$$)/
depends_on:
@@ -884,11 +868,30 @@ steps:
timeout_in_minutes: 10
retry: *auto-retry
+ - label: "end-to-end sqlserver sink test"
+ key: "e2e-sqlserver-sink-tests"
+ command: "ci/scripts/e2e-sqlserver-sink-test.sh -p ci-release"
+ if: |
+ !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ || build.pull_request.labels includes "ci/run-e2e-sqlserver-sink-tests"
+ || build.env("CI_STEPS") =~ /(^|,)e2e-sqlserver-sink-tests?(,|$$)/
+ depends_on:
+ - "build"
+ - "build-other"
+ plugins:
+ - docker-compose#v5.1.0:
+ run: sink-test-env
+ config: ci/docker-compose.yml
+ mount-buildkite-agent: true
+ - ./ci/plugins/upload-failure-logs
+ timeout_in_minutes: 10
+ retry: *auto-retry
+
- label: "end-to-end pulsar sink test"
key: "e2e-pulsar-sink-tests"
command: "ci/scripts/e2e-pulsar-sink-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-pulsar-sink-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-pulsar-sink-tests?(,|$$)/
depends_on:
@@ -907,7 +910,7 @@ steps:
key: "e2e-mqtt-sink-tests"
command: "ci/scripts/e2e-mqtt-sink-test.sh -p ci-release"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-mqtt-sink-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-mqtt-sink-tests?(,|$$)/
depends_on:
@@ -926,7 +929,7 @@ steps:
key: "connector-node-integration-test"
command: "ci/scripts/connector-node-integration-test.sh -p ci-release -v {{matrix.java_version}}"
if: |
- !(build.pull_request.labels includes "ci/main-cron/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/main-cron/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-connector-node-integration-tests"
|| build.env("CI_STEPS") =~ /(^|,)connector-node-integration-tests?(,|$$)/
depends_on:
diff --git a/ci/workflows/pull-request.yml b/ci/workflows/pull-request.yml
index 3f0c307bdab30..cc5e670fe078a 100644
--- a/ci/workflows/pull-request.yml
+++ b/ci/workflows/pull-request.yml
@@ -34,10 +34,6 @@ steps:
- label: "build"
command: "ci/scripts/build.sh -p ci-dev"
key: "build"
- if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
- || build.pull_request.labels includes "ci/run-build"
- || build.env("CI_STEPS") =~ /(^|,)build(,|$$)/
plugins:
- gencer/cache#v2.4.10: *cargo-cache
- docker-compose#v5.1.0:
@@ -50,10 +46,6 @@ steps:
- label: "build other components"
command: "ci/scripts/build-other.sh"
key: "build-other"
- if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
- || build.pull_request.labels includes "ci/run-build-other"
- || build.env("CI_STEPS") =~ /(^|,)build-other(,|$$)/
plugins:
- gencer/cache#v2.4.10: *cargo-cache
- seek-oss/aws-sm#v2.3.1:
@@ -71,10 +63,6 @@ steps:
- label: "build (deterministic simulation)"
command: "ci/scripts/build-simulation.sh"
key: "build-simulation"
- if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
- || build.pull_request.labels includes "ci/run-build-simulation"
- || build.env("CI_STEPS") =~ /(^|,)build-simulation(,|$$)/
plugins:
- gencer/cache#v2.4.10: *cargo-cache
- docker-compose#v5.1.0:
@@ -86,10 +74,6 @@ steps:
- label: "docslt"
command: "ci/scripts/docslt.sh"
key: "docslt"
- if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
- || build.pull_request.labels includes "ci/run-docslt"
- || build.env("CI_STEPS") =~ /(^|,)docslt(,|$$)/
plugins:
- gencer/cache#v2.4.10: *cargo-cache
- docker-compose#v5.1.0:
@@ -102,7 +86,7 @@ steps:
- label: "end-to-end test"
command: "ci/scripts/e2e-test.sh -p ci-dev -m ci-3streaming-2serving-3fe"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-test"
|| build.env("CI_STEPS") =~ /(^|,)e2e-tests?(,|$$)/
depends_on:
@@ -122,7 +106,7 @@ steps:
key: "slow-e2e-test"
command: "ci/scripts/slow-e2e-test.sh -p ci-dev -m ci-3streaming-2serving-3fe"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-slow-e2e-tests"
|| build.env("CI_STEPS") =~ /(^|,)slow-e2e-tests?(,|$$)/
depends_on:
@@ -137,10 +121,28 @@ steps:
timeout_in_minutes: 8
retry: *auto-retry
+ - label: "meta backup test"
+ key: "e2e-meta-backup-test"
+ command: "ci/scripts/run-meta-backup-test.sh -p ci-dev -m ci-3streaming-2serving-3fe"
+ if: |
+ build.pull_request.labels includes "ci/run-e2e-meta-backup-test"
+ depends_on:
+ - "build"
+ - "build-other"
+ - "docslt"
+ plugins:
+ - docker-compose#v5.1.0:
+ run: rw-build-env
+ config: ci/docker-compose.yml
+ mount-buildkite-agent: true
+ - ./ci/plugins/upload-failure-logs
+ timeout_in_minutes: 45
+ retry: *auto-retry
+
- label: "end-to-end test (parallel)"
command: "ci/scripts/e2e-test-parallel.sh -p ci-dev"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-parallel-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-parallel-tests?(,|$$)/
depends_on:
@@ -186,7 +188,7 @@ steps:
- label: "end-to-end source test"
command: "ci/scripts/e2e-source-test.sh -p ci-dev"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-source-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-source-tests?(,|$$)/
depends_on:
@@ -205,7 +207,7 @@ steps:
- label: "end-to-end sink test"
command: "ci/scripts/e2e-sink-test.sh -p ci-dev"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-sink-tests"
|| build.env("CI_STEPS") =~ /(^|,)e2e-sink-tests?(,|$$)/
depends_on:
@@ -331,6 +333,21 @@ steps:
timeout_in_minutes: 10
retry: *auto-retry
+ - label: "end-to-end sqlserver sink test"
+ if: build.pull_request.labels includes "ci/run-e2e-sqlserver-sink-tests" || build.env("CI_STEPS") =~ /(^|,)e2e-sqlserver-sink-tests?(,|$$)/
+ command: "ci/scripts/e2e-sqlserver-sink-test.sh -p ci-dev"
+ depends_on:
+ - "build"
+ - "build-other"
+ plugins:
+ - docker-compose#v5.1.0:
+ run: sink-test-env
+ config: ci/docker-compose.yml
+ mount-buildkite-agent: true
+ - ./ci/plugins/upload-failure-logs
+ timeout_in_minutes: 10
+ retry: *auto-retry
+
- label: "end-to-end deltalake sink test"
if: build.pull_request.labels includes "ci/run- e2e-deltalake-sink-rust-tests" || build.env("CI_STEPS") =~ /(^|,) e2e-deltalake-sink-rust-tests?(,|$$)/
command: "ci/scripts/e2e-deltalake-sink-rust-test.sh -p ci-dev"
@@ -424,7 +441,7 @@ steps:
- label: "regress test"
command: "ci/scripts/regress-test.sh -p ci-dev"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-regress-test"
|| build.env("CI_STEPS") =~ /(^|,)regress-tests?(,|$$)/
depends_on: "build"
@@ -443,7 +460,7 @@ steps:
- label: "unit test"
command: "ci/scripts/pr-unit-test.sh"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-unit-test"
|| build.env("CI_STEPS") =~ /(^|,)unit-tests?(,|$$)/
plugins:
@@ -463,7 +480,7 @@ steps:
- label: "check"
command: "ci/scripts/check.sh"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-check"
|| build.env("CI_STEPS") =~ /(^|,)check(,|$$)/
plugins:
@@ -477,7 +494,7 @@ steps:
- label: "check dylint"
command: "ci/scripts/check-dylint.sh"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-check"
|| build.env("CI_STEPS") =~ /(^|,)check(,|$$)/
plugins:
@@ -491,7 +508,7 @@ steps:
- label: "unit test (deterministic simulation)"
command: "ci/scripts/deterministic-unit-test.sh"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-unit-test-deterministic-simulation"
|| build.env("CI_STEPS") =~ /(^|,)unit-tests?-deterministic-simulation(,|$$)/
plugins:
@@ -506,7 +523,7 @@ steps:
- label: "integration test (deterministic simulation)"
command: "TEST_NUM=5 ci/scripts/deterministic-it-test.sh"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-integration-test-deterministic-simulation"
|| build.env("CI_STEPS") =~ /(^|,)integration-tests?-deterministic-simulation(,|$$)/
depends_on: "build-simulation"
@@ -522,7 +539,7 @@ steps:
- label: "end-to-end test (deterministic simulation)"
command: "TEST_NUM=16 ci/scripts/deterministic-e2e-test.sh"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-e2e-test-deterministic-simulation"
|| build.env("CI_STEPS") =~ /(^|,)e2e-tests?-deterministic-simulation(,|$$)/
depends_on: "build-simulation"
@@ -544,7 +561,7 @@ steps:
- label: "recovery test (deterministic simulation)"
command: "TEST_NUM=8 KILL_RATE=1.0 BACKGROUND_DDL_RATE=0.0 ci/scripts/deterministic-recovery-test.sh"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-recovery-test-deterministic-simulation"
|| build.env("CI_STEPS") =~ /(^|,)recovery-tests?-deterministic-simulation(,|$$)/
depends_on: "build-simulation"
@@ -568,7 +585,7 @@ steps:
- label: "misc check"
command: "ci/scripts/misc-check.sh"
if: |
- !(build.pull_request.labels includes "ci/skip-ci") && build.env("CI_STEPS") == null
+ !(build.pull_request.labels includes "ci/pr/run-selected") && build.env("CI_STEPS") == null
|| build.pull_request.labels includes "ci/run-misc-check"
|| build.env("CI_STEPS") =~ /(^|,)misc-check(,|$$)/
plugins:
@@ -786,10 +803,10 @@ steps:
timeout_in_minutes: 15
retry: *auto-retry
- - label: "enable ci/skip-ci only in draft PRs"
- if: build.pull_request.labels includes "ci/skip-ci" && !build.pull_request.draft
+ - label: "enable ci/pr/run-selected only in draft PRs"
+ if: build.pull_request.labels includes "ci/pr/run-selected" && !build.pull_request.draft
commands:
- - echo "ci/skip-ci is only usable for draft Pull Requests"
+ - echo "ci/pr/run-selected is only usable for draft Pull Requests"
- exit 1
- label: "micro benchmark"
diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json
index 5bf9ae127252e..857888e4d4cfe 100644
--- a/dashboard/package-lock.json
+++ b/dashboard/package-lock.json
@@ -3870,12 +3870,12 @@
}
},
"node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"dependencies": {
- "fill-range": "^7.0.1"
+ "fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
@@ -6325,9 +6325,9 @@
}
},
"node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
@@ -14516,12 +14516,12 @@
}
},
"braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"requires": {
- "fill-range": "^7.0.1"
+ "fill-range": "^7.1.1"
}
},
"browser-process-hrtime": {
@@ -16350,9 +16350,9 @@
}
},
"fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
diff --git a/docker/docker-compose-distributed.yml b/docker/docker-compose-distributed.yml
index f94437f089197..80ce64cb90531 100644
--- a/docker/docker-compose-distributed.yml
+++ b/docker/docker-compose-distributed.yml
@@ -1,5 +1,4 @@
---
-version: "3"
x-image: &image
image: ${RW_IMAGE:-risingwavelabs/risingwave:v1.9.1-rc.2}
services:
diff --git a/docker/docker-compose-with-azblob.yml b/docker/docker-compose-with-azblob.yml
index 9fc76c4051817..e1bf11bb28ff0 100644
--- a/docker/docker-compose-with-azblob.yml
+++ b/docker/docker-compose-with-azblob.yml
@@ -1,5 +1,4 @@
---
-version: "3"
x-image: &image
image: ${RW_IMAGE:-risingwavelabs/risingwave:v1.9.1-rc.2}
services:
diff --git a/docker/docker-compose-with-gcs.yml b/docker/docker-compose-with-gcs.yml
index 36433d549c1c7..fcad2692f474d 100644
--- a/docker/docker-compose-with-gcs.yml
+++ b/docker/docker-compose-with-gcs.yml
@@ -1,5 +1,4 @@
---
-version: "3"
x-image: &image
image: ${RW_IMAGE:-risingwavelabs/risingwave:v1.9.1-rc.2}
services:
diff --git a/docker/docker-compose-with-hdfs.yml b/docker/docker-compose-with-hdfs.yml
index cf2b45078bac5..974cf922e77b4 100644
--- a/docker/docker-compose-with-hdfs.yml
+++ b/docker/docker-compose-with-hdfs.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
compactor-0:
image: ghcr.io/risingwavelabs/risingwave:RisingWave_1.6.1_HDFS_2.7-x86_64
diff --git a/docker/docker-compose-with-local-fs.yml b/docker/docker-compose-with-local-fs.yml
index ab4545d649821..d7b5e22c36243 100644
--- a/docker/docker-compose-with-local-fs.yml
+++ b/docker/docker-compose-with-local-fs.yml
@@ -1,5 +1,4 @@
---
-version: "3"
x-image: &image
image: ${RW_IMAGE:-risingwavelabs/risingwave:v1.9.1-rc.2}
services:
diff --git a/docker/docker-compose-with-obs.yml b/docker/docker-compose-with-obs.yml
index b92d0cb077a16..45c84e32f652d 100644
--- a/docker/docker-compose-with-obs.yml
+++ b/docker/docker-compose-with-obs.yml
@@ -1,5 +1,4 @@
---
-version: "3"
x-image: &image
image: ${RW_IMAGE:-risingwavelabs/risingwave:v1.9.1-rc.2}
services:
diff --git a/docker/docker-compose-with-oss.yml b/docker/docker-compose-with-oss.yml
index adbfee86cc839..25aeae746e3b7 100644
--- a/docker/docker-compose-with-oss.yml
+++ b/docker/docker-compose-with-oss.yml
@@ -1,5 +1,4 @@
---
-version: "3"
x-image: &image
image: ${RW_IMAGE:-risingwavelabs/risingwave:v1.9.1-rc.2}
services:
diff --git a/docker/docker-compose-with-s3.yml b/docker/docker-compose-with-s3.yml
index eabe1f023ced7..75ffded8edcbc 100644
--- a/docker/docker-compose-with-s3.yml
+++ b/docker/docker-compose-with-s3.yml
@@ -1,5 +1,4 @@
---
-version: "3"
x-image: &image
image: ${RW_IMAGE:-risingwavelabs/risingwave:v1.9.1-rc.2}
services:
diff --git a/docker/docker-compose-with-sqlite.yml b/docker/docker-compose-with-sqlite.yml
index f65a4af7bc29f..065a60610f333 100644
--- a/docker/docker-compose-with-sqlite.yml
+++ b/docker/docker-compose-with-sqlite.yml
@@ -1,5 +1,4 @@
---
-version: "3"
x-image: &image
image: ${RW_IMAGE:-risingwavelabs/risingwave:v1.9.1-rc.2}
services:
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
index 5ba67f78c3f56..6042fbba261df 100644
--- a/docker/docker-compose.yml
+++ b/docker/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
x-image: &image
image: ${RW_IMAGE:-risingwavelabs/risingwave:v1.9.1-rc.2}
services:
diff --git a/docs/backfill.md b/docs/backfill.md
index 6784070853712..aac20615caf10 100644
--- a/docs/backfill.md
+++ b/docs/backfill.md
@@ -358,6 +358,22 @@ and arrangement backfill will consume this historical data snapshot:
| 1 | 'Jack' | 29 |
| 2 | 'Jill' | 30 |
+#### Initialization
+
+Something to note is that for the first snapshot,
+upstream may not have finished committing data in that epoch to s3.
+
+Additionally, we have not replicated any upstream records
+during that epoch, only in the subsequent ones.
+
+As such, we must wait for that first checkpoint to be committed,
+before reading, or we risk missing the uncommitted data in our backfill.
+
+This is supported internally inside `init_epoch` for replicated state table.
+```shell
+ upstream_table.init_epoch(first_epoch).await?;
+```
+
### Recovery
TODO
diff --git a/docs/developer-guide.md b/docs/developer-guide.md
index 054d33d4d7270..9b03c60f3d9a1 100644
--- a/docs/developer-guide.md
+++ b/docs/developer-guide.md
@@ -548,17 +548,18 @@ Instructions about submitting PRs are included in the [contribution guidelines](
## CI Labels Guide
-- `[ci/run-xxx ...]`: Run additional steps indicated by `ci/run-xxx` in your PR.
-- `ci/skip-ci` + `[ci/run-xxx ...]` : Skip steps except for those indicated by `ci/run-xxx` in your **DRAFT PR.**
-- `ci/run-main-cron`: Run full `main-cron`.
-- `ci/run-main-cron` + `ci/main-cron/skip-ci` + `[ci/run-xxx …]` : Run specific steps indicated by `ci/run-xxx`
+- `[ci/run-xxx ...]`: Run additional steps in the PR workflow indicated by `ci/run-xxx` in your PR.
+- `ci/pr/run-selected` + `[ci/run-xxx ...]` : Only run selected steps indicated by `ci/run-xxx` in your **DRAFT PR.**
+- `ci/main-cron/run-all`: Run full `main-cron` workflow for your PR.
+- `ci/main-cron/run-selected` + `[ci/run-xxx …]` : Run specific steps indicated by `ci/run-xxx`
from the `main-cron` workflow, in your PR. Can use to verify some `main-cron` fix works as expected.
- To reference `[ci/run-xxx ...]` labels, you may look at steps from `pull-request.yml` and `main-cron.yml`.
-- **Be sure to add all the dependencies.**
-
- For example to run `e2e-test` for `main-cron` in your pull request:
- 1. Add `ci/run-build`, `ci/run-build-other`, `ci/run-docslt` .
- These correspond to its `depends` field in `pull-request.yml` and `main-cron.yml` .
- 2. Add `ci/run-e2e-test` to run the step as well.
- 3. Add `ci/run-main-cron` to run `main-cron` workflow in your pull request,
- 4. Add `ci/main-cron/skip-ci` to skip all other steps which were not selected with `ci/run-xxx`.
+
+### Example
+
+https://github.com/risingwavelabs/risingwave/pull/17197
+
+To run `e2e-test` and `e2e-source-test` for `main-cron` in your pull request:
+1. Add `ci/run-e2e-test`.
+2. Add `ci/run-e2e-source-tests`.
+3. Add `ci/main-cron/run-selected` to skip all other steps which were not selected with `ci/run-xxx`.
\ No newline at end of file
diff --git a/e2e_test/backfill/sink/create_sink.slt b/e2e_test/backfill/sink/create_sink.slt
index 017eb8e693de2..016e3bcb2049b 100644
--- a/e2e_test/backfill/sink/create_sink.slt
+++ b/e2e_test/backfill/sink/create_sink.slt
@@ -5,9 +5,9 @@ statement ok
create table t (v1 int);
statement ok
-SET STREAMING_RATE_LIMIT = 1000;
+SET STREAMING_RATE_LIMIT = 500;
-# Should finish in 10s
+# Should finish in 20s
statement ok
insert into t select * from generate_series(1, 10000);
diff --git a/backwards-compat-tests/README.md b/e2e_test/backwards-compat-tests/README.md
similarity index 100%
rename from backwards-compat-tests/README.md
rename to e2e_test/backwards-compat-tests/README.md
diff --git a/backwards-compat-tests/scripts/run_local.sh b/e2e_test/backwards-compat-tests/scripts/run_local.sh
similarity index 96%
rename from backwards-compat-tests/scripts/run_local.sh
rename to e2e_test/backwards-compat-tests/scripts/run_local.sh
index e2604e6a114e0..7ac952e6d1c4a 100755
--- a/backwards-compat-tests/scripts/run_local.sh
+++ b/e2e_test/backwards-compat-tests/scripts/run_local.sh
@@ -10,7 +10,7 @@ on_exit() {
trap on_exit EXIT
-source backwards-compat-tests/scripts/utils.sh
+source e2e_test/backwards-compat-tests/scripts/utils.sh
configure_rw() {
VERSION="$1"
diff --git a/backwards-compat-tests/scripts/utils.sh b/e2e_test/backwards-compat-tests/scripts/utils.sh
similarity index 98%
rename from backwards-compat-tests/scripts/utils.sh
rename to e2e_test/backwards-compat-tests/scripts/utils.sh
index 6b5184b2bb0ea..8f41dad0860f1 100644
--- a/backwards-compat-tests/scripts/utils.sh
+++ b/e2e_test/backwards-compat-tests/scripts/utils.sh
@@ -18,9 +18,9 @@
RECOVERY_DURATION=20
# Setup test directory
-TEST_DIR=.risingwave/backwards-compat-tests/
+TEST_DIR=.risingwave/e2e_test/backwards-compat-tests/
mkdir -p $TEST_DIR
-cp -r backwards-compat-tests/slt/* $TEST_DIR
+cp -r e2e_test/backwards-compat-tests/slt/* $TEST_DIR
wait_for_process() {
process_name="$1"
diff --git a/backwards-compat-tests/slt/basic/seed.slt b/e2e_test/backwards-compat-tests/slt/basic/seed.slt
similarity index 100%
rename from backwards-compat-tests/slt/basic/seed.slt
rename to e2e_test/backwards-compat-tests/slt/basic/seed.slt
diff --git a/backwards-compat-tests/slt/basic/validate_original.slt b/e2e_test/backwards-compat-tests/slt/basic/validate_original.slt
similarity index 100%
rename from backwards-compat-tests/slt/basic/validate_original.slt
rename to e2e_test/backwards-compat-tests/slt/basic/validate_original.slt
diff --git a/backwards-compat-tests/slt/basic/validate_restart.slt b/e2e_test/backwards-compat-tests/slt/basic/validate_restart.slt
similarity index 100%
rename from backwards-compat-tests/slt/basic/validate_restart.slt
rename to e2e_test/backwards-compat-tests/slt/basic/validate_restart.slt
diff --git a/backwards-compat-tests/slt/kafka/invalid_options/seed.slt b/e2e_test/backwards-compat-tests/slt/kafka/invalid_options/seed.slt
similarity index 100%
rename from backwards-compat-tests/slt/kafka/invalid_options/seed.slt
rename to e2e_test/backwards-compat-tests/slt/kafka/invalid_options/seed.slt
diff --git a/backwards-compat-tests/slt/kafka/invalid_options/validate_original.slt b/e2e_test/backwards-compat-tests/slt/kafka/invalid_options/validate_original.slt
similarity index 100%
rename from backwards-compat-tests/slt/kafka/invalid_options/validate_original.slt
rename to e2e_test/backwards-compat-tests/slt/kafka/invalid_options/validate_original.slt
diff --git a/backwards-compat-tests/slt/kafka/invalid_options/validate_restart.slt b/e2e_test/backwards-compat-tests/slt/kafka/invalid_options/validate_restart.slt
similarity index 100%
rename from backwards-compat-tests/slt/kafka/invalid_options/validate_restart.slt
rename to e2e_test/backwards-compat-tests/slt/kafka/invalid_options/validate_restart.slt
diff --git a/backwards-compat-tests/slt/kafka/seed.slt b/e2e_test/backwards-compat-tests/slt/kafka/seed.slt
similarity index 100%
rename from backwards-compat-tests/slt/kafka/seed.slt
rename to e2e_test/backwards-compat-tests/slt/kafka/seed.slt
diff --git a/backwards-compat-tests/slt/kafka/upsert/deprecate_upsert.slt b/e2e_test/backwards-compat-tests/slt/kafka/upsert/deprecate_upsert.slt
similarity index 100%
rename from backwards-compat-tests/slt/kafka/upsert/deprecate_upsert.slt
rename to e2e_test/backwards-compat-tests/slt/kafka/upsert/deprecate_upsert.slt
diff --git a/backwards-compat-tests/slt/kafka/upsert/include_key_as.slt b/e2e_test/backwards-compat-tests/slt/kafka/upsert/include_key_as.slt
similarity index 100%
rename from backwards-compat-tests/slt/kafka/upsert/include_key_as.slt
rename to e2e_test/backwards-compat-tests/slt/kafka/upsert/include_key_as.slt
diff --git a/backwards-compat-tests/slt/kafka/validate_original.slt b/e2e_test/backwards-compat-tests/slt/kafka/validate_original.slt
similarity index 100%
rename from backwards-compat-tests/slt/kafka/validate_original.slt
rename to e2e_test/backwards-compat-tests/slt/kafka/validate_original.slt
diff --git a/backwards-compat-tests/slt/kafka/validate_restart.slt b/e2e_test/backwards-compat-tests/slt/kafka/validate_restart.slt
similarity index 100%
rename from backwards-compat-tests/slt/kafka/validate_restart.slt
rename to e2e_test/backwards-compat-tests/slt/kafka/validate_restart.slt
diff --git a/backwards-compat-tests/slt/nexmark-backwards-compat/delete.slt.part b/e2e_test/backwards-compat-tests/slt/nexmark-backwards-compat/delete.slt.part
similarity index 100%
rename from backwards-compat-tests/slt/nexmark-backwards-compat/delete.slt.part
rename to e2e_test/backwards-compat-tests/slt/nexmark-backwards-compat/delete.slt.part
diff --git a/backwards-compat-tests/slt/nexmark-backwards-compat/insert.slt b/e2e_test/backwards-compat-tests/slt/nexmark-backwards-compat/insert.slt
similarity index 100%
rename from backwards-compat-tests/slt/nexmark-backwards-compat/insert.slt
rename to e2e_test/backwards-compat-tests/slt/nexmark-backwards-compat/insert.slt
diff --git a/backwards-compat-tests/slt/nexmark-backwards-compat/seed.slt b/e2e_test/backwards-compat-tests/slt/nexmark-backwards-compat/seed.slt
similarity index 100%
rename from backwards-compat-tests/slt/nexmark-backwards-compat/seed.slt
rename to e2e_test/backwards-compat-tests/slt/nexmark-backwards-compat/seed.slt
diff --git a/backwards-compat-tests/slt/nexmark-backwards-compat/validate_original.slt b/e2e_test/backwards-compat-tests/slt/nexmark-backwards-compat/validate_original.slt
similarity index 100%
rename from backwards-compat-tests/slt/nexmark-backwards-compat/validate_original.slt
rename to e2e_test/backwards-compat-tests/slt/nexmark-backwards-compat/validate_original.slt
diff --git a/backwards-compat-tests/slt/nexmark-backwards-compat/validate_restart.slt b/e2e_test/backwards-compat-tests/slt/nexmark-backwards-compat/validate_restart.slt
similarity index 100%
rename from backwards-compat-tests/slt/nexmark-backwards-compat/validate_restart.slt
rename to e2e_test/backwards-compat-tests/slt/nexmark-backwards-compat/validate_restart.slt
diff --git a/backwards-compat-tests/slt/tpch-backwards-compat/delete.slt.part b/e2e_test/backwards-compat-tests/slt/tpch-backwards-compat/delete.slt.part
similarity index 100%
rename from backwards-compat-tests/slt/tpch-backwards-compat/delete.slt.part
rename to e2e_test/backwards-compat-tests/slt/tpch-backwards-compat/delete.slt.part
diff --git a/backwards-compat-tests/slt/tpch-backwards-compat/insert.slt.part b/e2e_test/backwards-compat-tests/slt/tpch-backwards-compat/insert.slt.part
similarity index 100%
rename from backwards-compat-tests/slt/tpch-backwards-compat/insert.slt.part
rename to e2e_test/backwards-compat-tests/slt/tpch-backwards-compat/insert.slt.part
diff --git a/backwards-compat-tests/slt/tpch-backwards-compat/seed.slt b/e2e_test/backwards-compat-tests/slt/tpch-backwards-compat/seed.slt
similarity index 100%
rename from backwards-compat-tests/slt/tpch-backwards-compat/seed.slt
rename to e2e_test/backwards-compat-tests/slt/tpch-backwards-compat/seed.slt
diff --git a/backwards-compat-tests/slt/tpch-backwards-compat/validate_original.slt b/e2e_test/backwards-compat-tests/slt/tpch-backwards-compat/validate_original.slt
similarity index 100%
rename from backwards-compat-tests/slt/tpch-backwards-compat/validate_original.slt
rename to e2e_test/backwards-compat-tests/slt/tpch-backwards-compat/validate_original.slt
diff --git a/backwards-compat-tests/slt/tpch-backwards-compat/validate_restart.slt b/e2e_test/backwards-compat-tests/slt/tpch-backwards-compat/validate_restart.slt
similarity index 100%
rename from backwards-compat-tests/slt/tpch-backwards-compat/validate_restart.slt
rename to e2e_test/backwards-compat-tests/slt/tpch-backwards-compat/validate_restart.slt
diff --git a/e2e_test/ddl/alter_set_schema.slt b/e2e_test/ddl/alter_set_schema.slt
index 9ea95e9cc09c2..74dcc5a77e64a 100644
--- a/e2e_test/ddl/alter_set_schema.slt
+++ b/e2e_test/ddl/alter_set_schema.slt
@@ -53,13 +53,14 @@ CREATE SOURCE test_source (v INT) WITH (
statement ok
ALTER SOURCE test_source SET SCHEMA test_schema;
-query TT
+query TT rowsort
SELECT name AS sourcename, nspname AS schemaname
FROM rw_sources
JOIN pg_namespace ON pg_namespace.oid = rw_sources.schema_id
WHERE nspname = 'test_schema';
----
test_source test_schema
+test_table test_schema
statement ok
CREATE SINK test_sink AS SELECT u FROM test_schema.test_table WITH (
diff --git a/e2e_test/sink/sqlserver_sink.slt b/e2e_test/sink/sqlserver_sink.slt
new file mode 100644
index 0000000000000..156b8b865ffc8
--- /dev/null
+++ b/e2e_test/sink/sqlserver_sink.slt
@@ -0,0 +1,59 @@
+statement ok
+create table t_many_data_type_rw (
+ k1 int, k2 int,
+ c_boolean bool,
+ c_int16 smallint,
+ c_int32 int,
+ c_int64 bigint,
+ c_float32 float,
+ c_float64 double,
+ c_decimal decimal,
+ c_date date,
+ c_time time,
+ c_timestamp timestamp,
+ c_timestampz timestamp,
+ c_nvarchar string,
+ c_varbinary bytea);
+
+statement ok
+create sink s_many_data_type from t_many_data_type_rw with (
+ connector = 'sqlserver',
+ type = 'upsert',
+ sqlserver.host = 'sqlserver-server',
+ sqlserver.port = 1433,
+ sqlserver.user = 'SA',
+ sqlserver.password = 'SomeTestOnly@SA',
+ sqlserver.database = 'SinkTest',
+ sqlserver.table = 't_many_data_type',
+ primary_key = 'k1,k2',
+);
+
+statement ok
+insert into t_many_data_type_rw values
+(0,0,false,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
+(1,1,false,1,1,1,1.0,1.0,1.0,date '2022-04-08',time '18:20:49','2022-03-13 01:00:00'::timestamp,'2022-03-13 01:00:00Z'::timestamptz,'Hello World!','\xDe00BeEf'),
+(1,2,false,2,2,1,1.0,1.0,1.0,date '2022-04-08',time '18:20:49','2022-03-13 01:00:00'::timestamp,'2022-03-13 01:00:00Z'::timestamptz,'Hello World!','\xDe00BeEf'),
+(1,3,false,2,2,1,1.0,1.0,1.0,date '2022-04-08',time '18:20:49','2022-03-13 01:00:00'::timestamp,'2022-03-13 01:00:00Z'::timestamptz,'Hello World!','\xDe00BeEf'),
+(1,4,false,2,2,1,1.0,1.0,1.0,date '2022-04-08',time '18:20:49','2022-03-13 01:00:00'::timestamp,'2022-03-13 01:00:00Z'::timestamptz,'Hello World!','\xDe00BeEf'),
+(1,1,false,2,2,1,1.0,1.0,1.0,date '2022-04-08',time '18:20:49','2022-03-13 01:00:00'::timestamp,'2022-03-13 01:00:00Z'::timestamptz,'Hello World!','\xDe00BeEf');
+flush;
+
+statement ok
+delete from t_many_data_type_rw where k1=1 and k2=2;
+delete from t_many_data_type_rw where k1=1 and k2=3;
+flush;
+
+statement ok
+insert into t_many_data_type_rw values
+(1,1,false,55,55,1,1.0,1.0,1.0,date '2022-04-08',time '18:20:49','2022-03-13 01:00:00'::timestamp,'2022-03-13 01:00:00Z'::timestamptz,'Hello World!','\xDe00BeEf'),
+(1,2,false,66,66,1,1.0,1.0,1.0,date '2022-04-08',time '18:20:49','2022-03-13 01:00:00'::timestamp,'2022-03-13 01:00:00Z'::timestamptz,'Hello World!','\xDe00BeEf');
+flush;
+
+statement ok
+FLUSH;
+
+statement ok
+DROP SINK s_many_data_type;
+
+statement ok
+DROP TABLE t_many_data_type_rw;
diff --git a/e2e_test_slow/backfill/rate_limit/slow-udf.slt b/e2e_test/slow_tests/backfill/rate_limit/slow-udf.slt
similarity index 100%
rename from e2e_test_slow/backfill/rate_limit/slow-udf.slt
rename to e2e_test/slow_tests/backfill/rate_limit/slow-udf.slt
diff --git a/e2e_test_slow/udf/always_retry_python.slt b/e2e_test/slow_tests/udf/always_retry_python.slt
similarity index 100%
rename from e2e_test_slow/udf/always_retry_python.slt
rename to e2e_test/slow_tests/udf/always_retry_python.slt
diff --git a/e2e_test/source/basic/ddl.slt b/e2e_test/source/basic/ddl.slt
index 465e0f19344e9..a56d90934c149 100644
--- a/e2e_test/source/basic/ddl.slt
+++ b/e2e_test/source/basic/ddl.slt
@@ -188,7 +188,7 @@ create table s (
query T
show sources
----
-
+s
query T
show tables
diff --git a/e2e_test/source/basic/nosim_kafka.slt b/e2e_test/source/basic/nosim_kafka.slt
index 0cef4889c3fe7..b773126c9a7c1 100644
--- a/e2e_test/source/basic/nosim_kafka.slt
+++ b/e2e_test/source/basic/nosim_kafka.slt
@@ -39,6 +39,22 @@ CREATE TABLE kafka_json_schema_plain with (
kafka.scan.startup.mode = 'earliest'
) FORMAT PLAIN ENCODE JSON (schema.registry = '${RISEDEV_SCHEMA_REGISTRY_URL}');
+
+query
+describe kafka_json_schema_plain;
+----
+dimensions (empty) false NULL
+map jsonb false NULL
+notMap (empty) false NULL
+price double precision false NULL
+productId bigint false NULL
+productName character varying false NULL
+tags character varying[] false NULL
+_row_id serial true NULL
+primary key _row_id NULL NULL
+distribution key _row_id NULL NULL
+table description kafka_json_schema_plain NULL NULL
+
statement ok
CREATE TABLE kafka_json_schema_upsert (PRIMARY KEY(rw_key))
INCLUDE KEY AS rw_key
@@ -83,10 +99,10 @@ select count(*) from debezium_compact;
query TFITT
select
- "dimensions", "price", "productId", "productName", "tags"
+ *
from kafka_json_schema_plain
----
-(9.5,7,12) 12.5 1 An ice sculpture {cold,ice}
+(9.5,7,12) {"foo": "bar"} (b) 12.5 1 An ice sculpture {cold,ice}
query TFITT
select
diff --git a/e2e_test/source/basic/old_row_format_syntax/ddl.slt b/e2e_test/source/basic/old_row_format_syntax/ddl.slt
index d5c41d4ded878..b48249ca7e393 100644
--- a/e2e_test/source/basic/old_row_format_syntax/ddl.slt
+++ b/e2e_test/source/basic/old_row_format_syntax/ddl.slt
@@ -142,7 +142,7 @@ create table s (
query T
show sources
----
-
+s
query T
show tables
diff --git a/integration_tests/ad-click/docker-compose.yml b/integration_tests/ad-click/docker-compose.yml
index 62d5c3fb76517..2b84bb00d9950 100644
--- a/integration_tests/ad-click/docker-compose.yml
+++ b/integration_tests/ad-click/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/ad-ctr/docker-compose.yml b/integration_tests/ad-ctr/docker-compose.yml
index 0298f014db11a..2bec6c35295b8 100644
--- a/integration_tests/ad-ctr/docker-compose.yml
+++ b/integration_tests/ad-ctr/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/big-query-sink/docker-compose.yml b/integration_tests/big-query-sink/docker-compose.yml
index 6c93903df8bba..279f43a43b217 100644
--- a/integration_tests/big-query-sink/docker-compose.yml
+++ b/integration_tests/big-query-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/cassandra-and-scylladb-sink/docker-compose.yml b/integration_tests/cassandra-and-scylladb-sink/docker-compose.yml
index 0fa224ddab9d0..9f09b203ef700 100644
--- a/integration_tests/cassandra-and-scylladb-sink/docker-compose.yml
+++ b/integration_tests/cassandra-and-scylladb-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
cassandra:
image: cassandra:4.0
diff --git a/integration_tests/cdn-metrics/docker-compose.yml b/integration_tests/cdn-metrics/docker-compose.yml
index 87adef35f8cf4..05d3d786e6279 100644
--- a/integration_tests/cdn-metrics/docker-compose.yml
+++ b/integration_tests/cdn-metrics/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/citus-cdc/docker-compose.yml b/integration_tests/citus-cdc/docker-compose.yml
index 6ce8341047ee4..8afb665e02cd1 100644
--- a/integration_tests/citus-cdc/docker-compose.yml
+++ b/integration_tests/citus-cdc/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/clickhouse-sink/docker-compose.yml b/integration_tests/clickhouse-sink/docker-compose.yml
index 1cf61ff8dfa30..beb2ee1254739 100644
--- a/integration_tests/clickhouse-sink/docker-compose.yml
+++ b/integration_tests/clickhouse-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
clickhouse-server:
image: clickhouse/clickhouse-server:23.3.8.21-alpine
diff --git a/integration_tests/clickstream/docker-compose.yml b/integration_tests/clickstream/docker-compose.yml
index 857c93f0d7577..4015a3a976ced 100644
--- a/integration_tests/clickstream/docker-compose.yml
+++ b/integration_tests/clickstream/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/client-library/docker-compose.yml b/integration_tests/client-library/docker-compose.yml
index c6868eaa42140..c8a03d353b18e 100644
--- a/integration_tests/client-library/docker-compose.yml
+++ b/integration_tests/client-library/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/cockroach-sink/docker-compose.yml b/integration_tests/cockroach-sink/docker-compose.yml
index b6b0c8d9e6c5f..d325c57865baf 100644
--- a/integration_tests/cockroach-sink/docker-compose.yml
+++ b/integration_tests/cockroach-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/debezium-mysql/docker-compose.yml b/integration_tests/debezium-mysql/docker-compose.yml
index 3462e5e3d09d1..6cb577ac23886 100644
--- a/integration_tests/debezium-mysql/docker-compose.yml
+++ b/integration_tests/debezium-mysql/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/debezium-postgres/docker-compose.yml b/integration_tests/debezium-postgres/docker-compose.yml
index c81c33fb3e455..327cb44d6db7c 100644
--- a/integration_tests/debezium-postgres/docker-compose.yml
+++ b/integration_tests/debezium-postgres/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/debezium-sqlserver/docker-compose.yml b/integration_tests/debezium-sqlserver/docker-compose.yml
index e88cb36e548b7..9d4bbbf0a5bb6 100644
--- a/integration_tests/debezium-sqlserver/docker-compose.yml
+++ b/integration_tests/debezium-sqlserver/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/deltalake-sink/docker-compose.yml b/integration_tests/deltalake-sink/docker-compose.yml
index 70b1e3c22e325..2a799f9fcf45b 100644
--- a/integration_tests/deltalake-sink/docker-compose.yml
+++ b/integration_tests/deltalake-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
spark:
image: apache/spark:3.3.1
diff --git a/integration_tests/doris-sink/docker-compose.yml b/integration_tests/doris-sink/docker-compose.yml
index e1a7f1ef5e90e..4b43632f51319 100644
--- a/integration_tests/doris-sink/docker-compose.yml
+++ b/integration_tests/doris-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
fe:
platform: linux/amd64
diff --git a/integration_tests/elasticsearch-sink/docker-compose.yml b/integration_tests/elasticsearch-sink/docker-compose.yml
index c885b7136a606..097de4beb5490 100644
--- a/integration_tests/elasticsearch-sink/docker-compose.yml
+++ b/integration_tests/elasticsearch-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
elasticsearch7:
image: docker.elastic.co/elasticsearch/elasticsearch:7.11.0
diff --git a/integration_tests/feature-store/docker-compose.yml b/integration_tests/feature-store/docker-compose.yml
index 71633cce20a19..77de22a8c3522 100644
--- a/integration_tests/feature-store/docker-compose.yml
+++ b/integration_tests/feature-store/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
kafka:
image: confluentinc/cp-kafka:7.1.0
diff --git a/integration_tests/http-sink/docker-compose.yml b/integration_tests/http-sink/docker-compose.yml
index 12546c4f5dd28..9a7c42b1443e0 100644
--- a/integration_tests/http-sink/docker-compose.yml
+++ b/integration_tests/http-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/iceberg-sink/docker-compose.yml b/integration_tests/iceberg-sink/docker-compose.yml
index 91cec5dd24430..84bda01b21ceb 100644
--- a/integration_tests/iceberg-sink/docker-compose.yml
+++ b/integration_tests/iceberg-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
x-airflow-common:
&airflow-common
image: apache/airflow:2.6.2-python3.10
diff --git a/integration_tests/kafka-cdc-sink/docker-compose.yml b/integration_tests/kafka-cdc-sink/docker-compose.yml
index 81f892354b8a0..1cebe9b73f284 100644
--- a/integration_tests/kafka-cdc-sink/docker-compose.yml
+++ b/integration_tests/kafka-cdc-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/kafka-cdc/docker-compose.yml b/integration_tests/kafka-cdc/docker-compose.yml
index f42c4399178d0..6eaa5b5ead7ab 100644
--- a/integration_tests/kafka-cdc/docker-compose.yml
+++ b/integration_tests/kafka-cdc/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/kinesis-s3-source/docker-compose.yml b/integration_tests/kinesis-s3-source/docker-compose.yml
index dc91e2095cbde..74dabde96f7ba 100644
--- a/integration_tests/kinesis-s3-source/docker-compose.yml
+++ b/integration_tests/kinesis-s3-source/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/livestream/docker-compose.yml b/integration_tests/livestream/docker-compose.yml
index 8dffce371562a..e263b704bc90d 100644
--- a/integration_tests/livestream/docker-compose.yml
+++ b/integration_tests/livestream/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/mindsdb/docker-compose.yml b/integration_tests/mindsdb/docker-compose.yml
index 40fe4e6192fa3..0cd82b10a6529 100644
--- a/integration_tests/mindsdb/docker-compose.yml
+++ b/integration_tests/mindsdb/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/mongodb-cdc/docker-compose.yaml b/integration_tests/mongodb-cdc/docker-compose.yaml
index eaf519b440569..de09a204d991b 100644
--- a/integration_tests/mongodb-cdc/docker-compose.yaml
+++ b/integration_tests/mongodb-cdc/docker-compose.yaml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/mongodb/docker-compose.yaml b/integration_tests/mongodb/docker-compose.yaml
index 59ac89215ec14..a2855c200e6b0 100644
--- a/integration_tests/mongodb/docker-compose.yaml
+++ b/integration_tests/mongodb/docker-compose.yaml
@@ -1,4 +1,3 @@
-version: "3"
services:
mongodb:
image: mongo:4.4
diff --git a/integration_tests/mqtt/docker-compose.yml b/integration_tests/mqtt/docker-compose.yml
index 04f73404be6aa..b91ddd482509c 100644
--- a/integration_tests/mqtt/docker-compose.yml
+++ b/integration_tests/mqtt/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/mysql-cdc/docker-compose.yml b/integration_tests/mysql-cdc/docker-compose.yml
index c0bba2ccc008b..b2779c42c05b6 100644
--- a/integration_tests/mysql-cdc/docker-compose.yml
+++ b/integration_tests/mysql-cdc/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/mysql-sink/docker-compose.yml b/integration_tests/mysql-sink/docker-compose.yml
index 3e1fc5544276f..8f8c4f9aa4336 100644
--- a/integration_tests/mysql-sink/docker-compose.yml
+++ b/integration_tests/mysql-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/nats/docker-compose.yml b/integration_tests/nats/docker-compose.yml
index 891c865744747..930f1a719fd7f 100644
--- a/integration_tests/nats/docker-compose.yml
+++ b/integration_tests/nats/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/pinot-sink/docker-compose.yml b/integration_tests/pinot-sink/docker-compose.yml
index fc4ad250880ce..c7d08dcc005e9 100644
--- a/integration_tests/pinot-sink/docker-compose.yml
+++ b/integration_tests/pinot-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/postgres-cdc/docker-compose.yml b/integration_tests/postgres-cdc/docker-compose.yml
index 7650da0779178..333ee2f4080c3 100644
--- a/integration_tests/postgres-cdc/docker-compose.yml
+++ b/integration_tests/postgres-cdc/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/postgres-sink/docker-compose.yml b/integration_tests/postgres-sink/docker-compose.yml
index 4d8638fdc3c07..6f5a16db64c24 100644
--- a/integration_tests/postgres-sink/docker-compose.yml
+++ b/integration_tests/postgres-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/presto-trino/docker-compose.yml b/integration_tests/presto-trino/docker-compose.yml
index a56135a4ae597..5de9dc34eb78a 100644
--- a/integration_tests/presto-trino/docker-compose.yml
+++ b/integration_tests/presto-trino/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/prometheus/docker-compose.yml b/integration_tests/prometheus/docker-compose.yml
index de3249df9253a..cd840807ea1ac 100644
--- a/integration_tests/prometheus/docker-compose.yml
+++ b/integration_tests/prometheus/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/redis-sink/docker-compose.yml b/integration_tests/redis-sink/docker-compose.yml
index dce27ae99895c..8f3c3eb9cdd85 100644
--- a/integration_tests/redis-sink/docker-compose.yml
+++ b/integration_tests/redis-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
redis:
image: 'redis:latest'
diff --git a/integration_tests/schema-registry/docker-compose.yml b/integration_tests/schema-registry/docker-compose.yml
index 80d4b90e4f7d2..2209fb7e20aee 100644
--- a/integration_tests/schema-registry/docker-compose.yml
+++ b/integration_tests/schema-registry/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/starrocks-sink/docker-compose.yml b/integration_tests/starrocks-sink/docker-compose.yml
index 70918713643d6..e3a06cc33587a 100644
--- a/integration_tests/starrocks-sink/docker-compose.yml
+++ b/integration_tests/starrocks-sink/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
starrocks-fe:
image: starrocks/fe-ubuntu:3.1.7
diff --git a/integration_tests/superset/docker-compose.yml b/integration_tests/superset/docker-compose.yml
index 746a80fb9a064..3d7b9ed2494ca 100644
--- a/integration_tests/superset/docker-compose.yml
+++ b/integration_tests/superset/docker-compose.yml
@@ -9,7 +9,6 @@ x-superset-volumes:
- ./docker:/app/docker
- superset_home:/app/superset_home
-version: "3.7"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/twitter-pulsar/docker-compose.yml b/integration_tests/twitter-pulsar/docker-compose.yml
index d684be6b876a8..a3e91c9f8751a 100644
--- a/integration_tests/twitter-pulsar/docker-compose.yml
+++ b/integration_tests/twitter-pulsar/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/twitter/docker-compose.yml b/integration_tests/twitter/docker-compose.yml
index 37b2723cb8e50..e59e71b3839ce 100644
--- a/integration_tests/twitter/docker-compose.yml
+++ b/integration_tests/twitter/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/integration_tests/upsert-avro/docker-compose.yml b/integration_tests/upsert-avro/docker-compose.yml
index 291528f6fb319..9176ca053ba4e 100644
--- a/integration_tests/upsert-avro/docker-compose.yml
+++ b/integration_tests/upsert-avro/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
@@ -53,4 +52,4 @@ volumes:
external: false
message_queue:
external: false
-name: risingwave-compose
\ No newline at end of file
+name: risingwave-compose
diff --git a/integration_tests/vector/docker-compose.yml b/integration_tests/vector/docker-compose.yml
index 4c2e6100b714a..13101925ac4a3 100644
--- a/integration_tests/vector/docker-compose.yml
+++ b/integration_tests/vector/docker-compose.yml
@@ -1,5 +1,4 @@
---
-version: "3"
services:
risingwave-standalone:
extends:
diff --git a/java/java-binding/src/main/java/com/risingwave/java/binding/Binding.java b/java/java-binding/src/main/java/com/risingwave/java/binding/Binding.java
index a16acda73e7fd..db832566fdfa7 100644
--- a/java/java-binding/src/main/java/com/risingwave/java/binding/Binding.java
+++ b/java/java-binding/src/main/java/com/risingwave/java/binding/Binding.java
@@ -26,6 +26,8 @@ public class Binding {
}
}
+ static void ensureInitialized() {}
+
public static native void tracingSlf4jEvent(
String threadName, String name, int level, String message);
@@ -33,10 +35,6 @@ public static native void tracingSlf4jEvent(
public static native int vnodeCount();
- // hummock iterator method
- // Return a pointer to the iterator
- static native long iteratorNewHummock(byte[] readPlan);
-
static native long iteratorNewStreamChunk(long pointer);
static native boolean iteratorNext(long pointer);
diff --git a/java/java-binding/src/main/java/com/risingwave/java/binding/HummockIterator.java b/java/java-binding/src/main/java/com/risingwave/java/binding/HummockIterator.java
index 03282a2dce528..a30391edbd380 100644
--- a/java/java-binding/src/main/java/com/risingwave/java/binding/HummockIterator.java
+++ b/java/java-binding/src/main/java/com/risingwave/java/binding/HummockIterator.java
@@ -20,8 +20,16 @@ public class HummockIterator implements AutoCloseable {
private final long pointer;
private boolean isClosed;
+ static {
+ Binding.ensureInitialized();
+ }
+
+ // hummock iterator method
+ // Return a pointer to the iterator
+ private static native long iteratorNewHummock(byte[] readPlan);
+
public HummockIterator(ReadPlan readPlan) {
- this.pointer = Binding.iteratorNewHummock(readPlan.toByteArray());
+ this.pointer = iteratorNewHummock(readPlan.toByteArray());
this.isClosed = false;
}
diff --git a/java/pom.xml b/java/pom.xml
index f1ee457ef3b84..5f0327bf8ffc9 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -83,7 +83,7 @@
1.18.0
1.17.6
42.5.5
- 8.0.33
+ 8.3.0
4.11.1
3.45.0.0
2.21.42
@@ -570,4 +570,4 @@
https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
-
\ No newline at end of file
+
diff --git a/proto/backup_service.proto b/proto/backup_service.proto
index 75420149042d9..24d410b38f115 100644
--- a/proto/backup_service.proto
+++ b/proto/backup_service.proto
@@ -2,6 +2,8 @@ syntax = "proto3";
package backup_service;
+import "hummock.proto";
+
option java_package = "com.risingwave.proto";
option optimize_for = SPEED;
@@ -49,6 +51,8 @@ message MetaSnapshotMetadata {
uint64 safe_epoch = 4;
optional uint32 format_version = 5;
optional string remarks = 6;
+ optional string rw_version = 7;
+ map state_table_info = 8;
}
service BackupService {
diff --git a/proto/expr.proto b/proto/expr.proto
index 998ed63a4b084..9abb1d74f4955 100644
--- a/proto/expr.proto
+++ b/proto/expr.proto
@@ -280,6 +280,7 @@ message ExprNode {
JSONB_PATH_QUERY_FIRST = 623;
JSONB_POPULATE_RECORD = 629;
JSONB_TO_RECORD = 630;
+ JSONB_SET = 631;
// Non-pure functions below (> 1000)
// ------------------------
diff --git a/proto/hummock.proto b/proto/hummock.proto
index 2fc4c1a6d4b42..89a0438fc43a7 100644
--- a/proto/hummock.proto
+++ b/proto/hummock.proto
@@ -340,6 +340,7 @@ message CompactTask {
JOIN_HANDLE_FAILED = 11;
TRACK_SST_OBJECT_ID_FAILED = 12;
NO_AVAIL_CPU_RESOURCE_CANCELED = 13;
+ HEARTBEAT_PROGRESS_CANCELED = 14;
}
// SSTs to be compacted, which will be removed from LSM after compaction
repeated InputLevel input_ssts = 1;
@@ -706,6 +707,7 @@ message RiseCtlUpdateCompactionConfigRequest {
bool enable_emergency_picker = 15;
uint32 tombstone_reclaim_ratio = 16;
CompressionAlgorithm compression_algorithm = 17;
+ uint32 max_l0_compact_level_count = 18;
}
}
repeated uint64 compaction_group_ids = 1;
@@ -885,6 +887,9 @@ message CompactionConfig {
uint32 level0_overlapping_sub_level_compact_level_count = 18;
uint32 tombstone_reclaim_ratio = 19;
bool enable_emergency_picker = 20;
+
+ // The limitation of the level count of l0 compaction
+ uint32 max_l0_compact_level_count = 21;
}
message TableStats {
diff --git a/scripts/source/test_data/kafka_json_schema.1 b/scripts/source/test_data/kafka_json_schema.1
index e71485885a654..afa96107864cb 100644
--- a/scripts/source/test_data/kafka_json_schema.1
+++ b/scripts/source/test_data/kafka_json_schema.1
@@ -1,2 +1,2 @@
-{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/product.schema.json","title":"Product","description":"A product from Acme's catalog","type":"object","properties":{"productId":{"description":"The unique identifier for a product","type":"integer"},"productName":{"description":"Name of the product","type":"string"},"price":{"description":"The price of the product","type":"number","exclusiveMinimum":0},"tags":{"description":"Tags for the product","type":"array","items":{"type":"string"},"minItems":1,"uniqueItems":true},"dimensions":{"type":"object","properties":{"length":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"}},"required":["length","width","height"]}},"required":["productId","productName","price"]}
-{"productId":1,"productName":"An ice sculpture","price":12.5,"tags":["cold","ice"],"dimensions":{"length":7,"width":12,"height":9.5}}
\ No newline at end of file
+{"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://example.com/product.schema.json","title":"Product","description":"A product from Acme's catalog","type":"object","properties":{"productId":{"description":"The unique identifier for a product","type":"integer"},"productName":{"description":"Name of the product","type":"string"},"price":{"description":"The price of the product","type":"number","exclusiveMinimum":0},"tags":{"description":"Tags for the product","type":"array","items":{"type":"string"},"minItems":1,"uniqueItems":true},"dimensions":{"type":"object","properties":{"length":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"}},"required":["length","width","height"]},"map":{"type":"object","additionalProperties":{"type":"string"}},"notMap":{"type":"object","additionalProperties":{"type":"string"},"properties":{"a":{"type":"string"}}}},"required":["productId","productName","price"]}
+{"productId":1,"productName":"An ice sculpture","price":12.5,"tags":["cold","ice"],"dimensions":{"length":7,"width":12,"height":9.5},"map":{"foo":"bar"},"notMap":{"a":"b","ignored":"c"}}
\ No newline at end of file
diff --git a/src/batch/src/executor/merge_sort_exchange.rs b/src/batch/src/executor/merge_sort_exchange.rs
index 3c0f13198a3ae..e2779967dbcbe 100644
--- a/src/batch/src/executor/merge_sort_exchange.rs
+++ b/src/batch/src/executor/merge_sort_exchange.rs
@@ -123,7 +123,7 @@ impl MergeSortExchangeEx
// Check whether there is indeed a chunk and there is a visible row sitting at `row_idx`
// in the chunk before calling this function.
- fn push_row_into_heap(&mut self, source_idx: usize, row_idx: usize) -> Result<()> {
+ fn push_row_into_heap(&mut self, source_idx: usize, row_idx: usize) {
assert!(source_idx < self.source_inputs.len());
let chunk_ref = self.source_inputs[source_idx].as_ref().unwrap();
self.min_heap.push(HeapElem::new(
@@ -133,14 +133,6 @@ impl MergeSortExchangeEx
row_idx,
None,
));
-
- if self.min_heap.mem_context().check_memory_usage() {
- Ok(())
- } else {
- Err(BatchError::OutOfMemory(
- self.min_heap.mem_context().mem_limit(),
- ))
- }
}
}
@@ -176,7 +168,7 @@ impl MergeSortExchangeEx
// exchange, therefore we are sure that there is at least
// one visible row.
let next_row_idx = chunk.next_visible_row_idx(0);
- self.push_row_into_heap(source_idx, next_row_idx.unwrap())?;
+ self.push_row_into_heap(source_idx, next_row_idx.unwrap());
}
}
@@ -211,13 +203,13 @@ impl MergeSortExchangeEx
let possible_next_row_idx = cur_chunk.next_visible_row_idx(row_idx + 1);
match possible_next_row_idx {
Some(next_row_idx) => {
- self.push_row_into_heap(child_idx, next_row_idx)?;
+ self.push_row_into_heap(child_idx, next_row_idx);
}
None => {
self.get_source_chunk(child_idx).await?;
if let Some(chunk) = &self.source_inputs[child_idx] {
let next_row_idx = chunk.next_visible_row_idx(0);
- self.push_row_into_heap(child_idx, next_row_idx.unwrap())?;
+ self.push_row_into_heap(child_idx, next_row_idx.unwrap());
}
}
}
diff --git a/src/batch/src/executor/order_by.rs b/src/batch/src/executor/order_by.rs
index fd07b4fab845e..05cd0f8c94fa0 100644
--- a/src/batch/src/executor/order_by.rs
+++ b/src/batch/src/executor/order_by.rs
@@ -19,6 +19,7 @@ use risingwave_common::memory::MemoryContext;
use risingwave_common::util::chunk_coalesce::DataChunkBuilder;
use risingwave_common::util::memcmp_encoding::encode_chunk;
use risingwave_common::util::sort_util::ColumnOrder;
+use risingwave_common_estimate_size::EstimateSize;
use risingwave_pb::batch_plan::plan_node::NodeBody;
use super::{BoxedDataChunkStream, BoxedExecutor, BoxedExecutorBuilder, Executor, ExecutorBuilder};
@@ -91,7 +92,12 @@ impl SortExecutor {
#[for_await]
for chunk in self.child.execute() {
- chunks.push(chunk?.compact());
+ let chunk = chunk?.compact();
+ let chunk_estimated_heap_size = chunk.estimated_heap_size();
+ chunks.push(chunk);
+ if !self.mem_context.add(chunk_estimated_heap_size as i64) {
+ Err(BatchError::OutOfMemory(self.mem_context.mem_limit()))?;
+ }
}
let mut encoded_rows =
@@ -99,12 +105,19 @@ impl SortExecutor {
for chunk in &chunks {
let encoded_chunk = encode_chunk(chunk, &self.column_orders)?;
+ let chunk_estimated_heap_size = encoded_chunk
+ .iter()
+ .map(|x| x.estimated_heap_size())
+ .sum::();
encoded_rows.extend(
encoded_chunk
.into_iter()
.enumerate()
.map(|(row_id, row)| (chunk.row_at_unchecked_vis(row_id), row)),
);
+ if !self.mem_context.add(chunk_estimated_heap_size as i64) {
+ Err(BatchError::OutOfMemory(self.mem_context.mem_limit()))?;
+ }
}
encoded_rows.sort_unstable_by(|(_, a), (_, b)| a.cmp(b));
diff --git a/src/common/src/config.rs b/src/common/src/config.rs
index 3b6dec9829128..d8bb65e90b062 100644
--- a/src/common/src/config.rs
+++ b/src/common/src/config.rs
@@ -763,6 +763,14 @@ pub struct StorageConfig {
#[serde(default = "default::storage::mem_table_spill_threshold")]
pub mem_table_spill_threshold: usize,
+ /// The concurrent uploading number of `SSTables` of buidler
+ #[serde(default = "default::storage::compactor_concurrent_uploading_sst_count")]
+ pub compactor_concurrent_uploading_sst_count: Option,
+
+ /// Object storage configuration
+ /// 1. General configuration
+ /// 2. Some special configuration of Backend
+ /// 3. Retry and timeout configuration
#[serde(default)]
pub object_store: ObjectStoreConfig,
}
@@ -827,12 +835,6 @@ pub struct FileCacheConfig {
#[serde(default = "default::file_cache::recover_concurrency")]
pub recover_concurrency: usize,
- #[serde(default = "default::file_cache::lfu_window_to_cache_size_ratio")]
- pub lfu_window_to_cache_size_ratio: usize,
-
- #[serde(default = "default::file_cache::lfu_tiny_lru_capacity_ratio")]
- pub lfu_tiny_lru_capacity_ratio: f64,
-
#[serde(default = "default::file_cache::insert_rate_limit_mb")]
pub insert_rate_limit_mb: usize,
@@ -1030,9 +1032,13 @@ pub struct ObjectStoreConfig {
#[serde(default = "default::object_store_config::object_store_set_atomic_write_dir")]
pub object_store_set_atomic_write_dir: bool,
+ /// Retry and timeout configuration
+ /// Description retry strategy driven by exponential back-off
+ /// Exposes the timeout and retries of each Object store interface. Therefore, the total timeout for each interface is determined based on the interface's timeout/retry configuration and the exponential back-off policy.
#[serde(default)]
pub retry: ObjectStoreRetryConfig,
+ /// Some special configuration of S3 Backend
#[serde(default)]
pub s3: S3ObjectStoreConfig,
}
@@ -1086,66 +1092,89 @@ pub struct S3ObjectStoreDeveloperConfig {
#[derive(Clone, Debug, Serialize, Deserialize, DefaultFromSerde)]
pub struct ObjectStoreRetryConfig {
+ // A retry strategy driven by exponential back-off.
+ // The retry strategy is used for all object store operations.
+ /// Given a base duration for retry strategy in milliseconds.
#[serde(default = "default::object_store_config::object_store_req_backoff_interval_ms")]
pub req_backoff_interval_ms: u64,
+
+ /// The max delay interval for the retry strategy. No retry delay will be longer than this `Duration`.
#[serde(default = "default::object_store_config::object_store_req_backoff_max_delay_ms")]
pub req_backoff_max_delay_ms: u64,
+
+ /// A multiplicative factor that will be applied to the exponential back-off retry delay.
#[serde(default = "default::object_store_config::object_store_req_backoff_factor")]
pub req_backoff_factor: u64,
- // upload
+ /// Maximum timeout for `upload` operation
#[serde(default = "default::object_store_config::object_store_upload_attempt_timeout_ms")]
pub upload_attempt_timeout_ms: u64,
+
+ /// Total counts of `upload` operation retries
#[serde(default = "default::object_store_config::object_store_upload_retry_attempts")]
pub upload_retry_attempts: usize,
- // streaming_upload_init + streaming_upload
+ /// Maximum timeout for `streaming_upload_init` and `streaming_upload`
#[serde(
default = "default::object_store_config::object_store_streaming_upload_attempt_timeout_ms"
)]
pub streaming_upload_attempt_timeout_ms: u64,
+
+ /// Total counts of `streaming_upload` operation retries
#[serde(
default = "default::object_store_config::object_store_streaming_upload_retry_attempts"
)]
pub streaming_upload_retry_attempts: usize,
- // read
+ /// Maximum timeout for `read` operation
#[serde(default = "default::object_store_config::object_store_read_attempt_timeout_ms")]
pub read_attempt_timeout_ms: u64,
+
+ /// Total counts of `read` operation retries
#[serde(default = "default::object_store_config::object_store_read_retry_attempts")]
pub read_retry_attempts: usize,
- // streaming_read_init + streaming_read
+ /// Maximum timeout for `streaming_read_init` and `streaming_read` operation
#[serde(
default = "default::object_store_config::object_store_streaming_read_attempt_timeout_ms"
)]
pub streaming_read_attempt_timeout_ms: u64,
+
+ /// Total counts of `streaming_read operation` retries
#[serde(default = "default::object_store_config::object_store_streaming_read_retry_attempts")]
pub streaming_read_retry_attempts: usize,
- // metadata
+ /// Maximum timeout for `metadata` operation
#[serde(default = "default::object_store_config::object_store_metadata_attempt_timeout_ms")]
pub metadata_attempt_timeout_ms: u64,
+
+ /// Total counts of `metadata` operation retries
#[serde(default = "default::object_store_config::object_store_metadata_retry_attempts")]
pub metadata_retry_attempts: usize,
- // delete
+ /// Maximum timeout for `delete` operation
#[serde(default = "default::object_store_config::object_store_delete_attempt_timeout_ms")]
pub delete_attempt_timeout_ms: u64,
+
+ /// Total counts of `delete` operation retries
#[serde(default = "default::object_store_config::object_store_delete_retry_attempts")]
pub delete_retry_attempts: usize,
- // delete_object
+ /// Maximum timeout for `delete_object` operation
#[serde(
default = "default::object_store_config::object_store_delete_objects_attempt_timeout_ms"
)]
pub delete_objects_attempt_timeout_ms: u64,
+
+ /// Total counts of `delete_object` operation retries
#[serde(default = "default::object_store_config::object_store_delete_objects_retry_attempts")]
pub delete_objects_retry_attempts: usize,
- // list
+ /// Maximum timeout for `list` operation
#[serde(default = "default::object_store_config::object_store_list_attempt_timeout_ms")]
pub list_attempt_timeout_ms: u64,
+
+ /// Total counts of `list` operation retries
#[serde(default = "default::object_store_config::object_store_list_retry_attempts")]
pub list_retry_attempts: usize,
}
@@ -1515,6 +1544,10 @@ pub mod default {
pub fn max_prefetch_block_number() -> usize {
16
}
+
+ pub fn compactor_concurrent_uploading_sst_count() -> Option {
+ None
+ }
}
pub mod streaming {
@@ -1564,14 +1597,6 @@ pub mod default {
8
}
- pub fn lfu_window_to_cache_size_ratio() -> usize {
- 1
- }
-
- pub fn lfu_tiny_lru_capacity_ratio() -> f64 {
- 0.01
- }
-
pub fn insert_rate_limit_mb() -> usize {
0
}
@@ -1800,8 +1825,8 @@ pub mod default {
const DEFAULT_MIN_OVERLAPPING_SUB_LEVEL_COMPACT_LEVEL_COUNT: u32 = 12;
const DEFAULT_TOMBSTONE_RATIO_PERCENT: u32 = 40;
const DEFAULT_EMERGENCY_PICKER: bool = true;
-
const DEFAULT_MAX_LEVEL: u32 = 6;
+ const DEFAULT_MAX_L0_COMPACT_LEVEL_COUNT: u32 = 42;
use crate::catalog::hummock::CompactionFilterFlag;
@@ -1868,6 +1893,10 @@ pub mod default {
pub fn max_level() -> u32 {
DEFAULT_MAX_LEVEL
}
+
+ pub fn max_l0_compact_level_count() -> u32 {
+ DEFAULT_MAX_L0_COMPACT_LEVEL_COUNT
+ }
}
pub mod object_store_config {
diff --git a/src/common/src/types/cow.rs b/src/common/src/types/cow.rs
index 928af654b0366..88eebfe1e4c2a 100644
--- a/src/common/src/types/cow.rs
+++ b/src/common/src/types/cow.rs
@@ -73,3 +73,8 @@ impl ToOwnedDatum for DatumCow<'_> {
}
}
}
+
+impl DatumCow<'_> {
+ /// Equivalent to `DatumCow::Owned(Datum::None)`.
+ pub const NULL: DatumCow<'static> = DatumCow::Owned(None);
+}
diff --git a/src/common/src/types/jsonb.rs b/src/common/src/types/jsonb.rs
index 824020fac3123..642b363a8c67e 100644
--- a/src/common/src/types/jsonb.rs
+++ b/src/common/src/types/jsonb.rs
@@ -239,10 +239,15 @@ impl<'a> JsonbRef<'a> {
}
/// Returns a jsonb `null` value.
- pub fn null() -> Self {
+ pub const fn null() -> Self {
Self(ValueRef::Null)
}
+ /// Returns a value for empty string.
+ pub const fn empty_string() -> Self {
+ Self(ValueRef::String(""))
+ }
+
/// Returns true if this is a jsonb `null`.
pub fn is_jsonb_null(&self) -> bool {
self.0.is_null()
diff --git a/src/compute/src/memory/config.rs b/src/compute/src/memory/config.rs
index 2a908d850f3f1..2a6607c268a67 100644
--- a/src/compute/src/memory/config.rs
+++ b/src/compute/src/memory/config.rs
@@ -27,7 +27,9 @@ pub const MIN_COMPUTE_MEMORY_MB: usize = 512;
/// overhead, network buffer, etc.) in megabytes.
pub const MIN_SYSTEM_RESERVED_MEMORY_MB: usize = 512;
-const SYSTEM_RESERVED_MEMORY_PROPORTION: f64 = 0.3;
+const RESERVED_MEMORY_LEVELS: [usize; 2] = [16 << 30, usize::MAX];
+
+const RESERVED_MEMORY_PROPORTIONS: [f64; 2] = [0.3, 0.2];
const STORAGE_MEMORY_PROPORTION: f64 = 0.3;
@@ -44,7 +46,7 @@ const STORAGE_SHARED_BUFFER_MEMORY_PROPORTION: f64 = 0.3;
const COMPUTE_BATCH_MEMORY_PROPORTION: f64 = 0.3;
/// Each compute node reserves some memory for stack and code segment of processes, allocation
-/// overhead, network buffer, etc. based on `SYSTEM_RESERVED_MEMORY_PROPORTION`. The reserve memory
+/// overhead, network buffer, etc. based on gradient reserve memory proportion. The reserve memory
/// size must be larger than `MIN_SYSTEM_RESERVED_MEMORY_MB`
pub fn reserve_memory_bytes(opts: &ComputeNodeOpts) -> (usize, usize) {
if opts.total_memory_bytes < MIN_COMPUTE_MEMORY_MB << 20 {
@@ -55,10 +57,10 @@ pub fn reserve_memory_bytes(opts: &ComputeNodeOpts) -> (usize, usize) {
);
}
- // If `reserved_memory_bytes` is not set, use `SYSTEM_RESERVED_MEMORY_PROPORTION` * `total_memory_bytes`.
- let reserved = opts.reserved_memory_bytes.unwrap_or_else(|| {
- (opts.total_memory_bytes as f64 * SYSTEM_RESERVED_MEMORY_PROPORTION).ceil() as usize
- });
+ // If `reserved_memory_bytes` is not set, calculate total_memory_bytes based on gradient reserve memory proportion.
+ let reserved = opts
+ .reserved_memory_bytes
+ .unwrap_or_else(|| gradient_reserve_memory_bytes(opts.total_memory_bytes));
// Should have at least `MIN_SYSTEM_RESERVED_MEMORY_MB` for reserved memory.
let reserved = std::cmp::max(reserved, MIN_SYSTEM_RESERVED_MEMORY_MB << 20);
@@ -66,6 +68,31 @@ pub fn reserve_memory_bytes(opts: &ComputeNodeOpts) -> (usize, usize) {
(reserved, opts.total_memory_bytes - reserved)
}
+/// Calculate the reserved memory based on the total memory size.
+/// The reserved memory size is calculated based on the following gradient:
+/// - 30% of the first 16GB
+/// - 20% of the rest
+fn gradient_reserve_memory_bytes(total_memory_bytes: usize) -> usize {
+ let mut total_memory_bytes = total_memory_bytes;
+ let mut reserved = 0;
+ for i in 0..RESERVED_MEMORY_LEVELS.len() {
+ let level_diff = if i == 0 {
+ RESERVED_MEMORY_LEVELS[0]
+ } else {
+ RESERVED_MEMORY_LEVELS[i] - RESERVED_MEMORY_LEVELS[i - 1]
+ };
+ if total_memory_bytes <= level_diff {
+ reserved += (total_memory_bytes as f64 * RESERVED_MEMORY_PROPORTIONS[i]) as usize;
+ break;
+ } else {
+ reserved += (level_diff as f64 * RESERVED_MEMORY_PROPORTIONS[i]) as usize;
+ total_memory_bytes -= level_diff;
+ }
+ }
+
+ reserved
+}
+
/// Decide the memory limit for each storage cache. If not specified in `StorageConfig`, memory
/// limits are calculated based on the proportions to total `non_reserved_memory_bytes`.
pub fn storage_memory_config(
@@ -346,4 +373,17 @@ mod tests {
assert_eq!(memory_config.shared_buffer_capacity_mb, 1024);
assert_eq!(memory_config.compactor_memory_limit_mb, 512);
}
+
+ #[test]
+ fn test_gradient_reserve_memory_bytes() {
+ assert_eq!(super::gradient_reserve_memory_bytes(4 << 30), 1288490188);
+ assert_eq!(super::gradient_reserve_memory_bytes(8 << 30), 2576980377);
+ assert_eq!(super::gradient_reserve_memory_bytes(16 << 30), 5153960755);
+ assert_eq!(super::gradient_reserve_memory_bytes(24 << 30), 6871947673);
+ assert_eq!(super::gradient_reserve_memory_bytes(32 << 30), 8589934591);
+ assert_eq!(super::gradient_reserve_memory_bytes(54 << 30), 13314398617);
+ assert_eq!(super::gradient_reserve_memory_bytes(64 << 30), 15461882265);
+ assert_eq!(super::gradient_reserve_memory_bytes(100 << 30), 23192823398);
+ assert_eq!(super::gradient_reserve_memory_bytes(128 << 30), 29205777612);
+ }
}
diff --git a/src/config/docs.md b/src/config/docs.md
index 540d86085b342..ab33559260162 100644
--- a/src/config/docs.md
+++ b/src/config/docs.md
@@ -105,6 +105,7 @@ This page is automatically generated by `./risedev generate-example-config`
| cache_refill | | |
| check_compaction_result | | false |
| compact_iter_recreate_timeout_ms | | 600000 |
+| compactor_concurrent_uploading_sst_count | The concurrent uploading number of `SSTables` of buidler | |
| compactor_fast_max_compact_delete_ratio | | 40 |
| compactor_fast_max_compact_task_size | | 2147483648 |
| compactor_iter_max_io_retry_times | | 8 |
@@ -128,7 +129,7 @@ This page is automatically generated by `./risedev generate-example-config`
| meta_file_cache | | |
| min_sst_size_for_streaming_upload | Whether to enable streaming upload for sstable. | 33554432 |
| min_sstable_size_mb | | 32 |
-| object_store | | |
+| object_store | Object storage configuration 1. General configuration 2. Some special configuration of Backend 3. Retry and timeout configuration | |
| prefetch_buffer_capacity_mb | max memory usage for large query | |
| share_buffer_compaction_worker_threads_number | Worker threads number of dedicated tokio runtime for share buffer compaction. 0 means use tokio's default value (number of CPU core). | 4 |
| share_buffer_upload_concurrency | Number of tasks shared buffer can upload in parallel. | 8 |
diff --git a/src/config/example.toml b/src/config/example.toml
index d3d0af3fe6cd1..b35590c85059b 100644
--- a/src/config/example.toml
+++ b/src/config/example.toml
@@ -165,8 +165,6 @@ file_capacity_mb = 64
flushers = 4
reclaimers = 4
recover_concurrency = 8
-lfu_window_to_cache_size_ratio = 1
-lfu_tiny_lru_capacity_ratio = 0.01
insert_rate_limit_mb = 0
indexer_shards = 64
compression = "none"
@@ -178,8 +176,6 @@ file_capacity_mb = 64
flushers = 4
reclaimers = 4
recover_concurrency = 8
-lfu_window_to_cache_size_ratio = 1
-lfu_tiny_lru_capacity_ratio = 0.01
insert_rate_limit_mb = 0
indexer_shards = 64
compression = "none"
diff --git a/src/connector/Cargo.toml b/src/connector/Cargo.toml
index 1464fcc215b32..7cb6f23e5ec7e 100644
--- a/src/connector/Cargo.toml
+++ b/src/connector/Cargo.toml
@@ -136,6 +136,7 @@ strum_macros = "0.26"
tempfile = "3"
thiserror = "1"
thiserror-ext = { workspace = true }
+tiberius = { version = "0.12", default-features = false, features = ["chrono", "time", "tds73", "rust_decimal", "bigdecimal", "rustls"] }
time = "0.3.30"
tokio = { version = "0.2", package = "madsim-tokio", features = [
"rt",
diff --git a/src/connector/benches/nexmark_integration.rs b/src/connector/benches/nexmark_integration.rs
index c2c735d1c2089..172931562efef 100644
--- a/src/connector/benches/nexmark_integration.rs
+++ b/src/connector/benches/nexmark_integration.rs
@@ -26,7 +26,7 @@ use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use futures::{FutureExt, StreamExt, TryStreamExt};
use itertools::Itertools;
use risingwave_common::array::StreamChunk;
-use risingwave_common::catalog::ColumnId;
+use risingwave_common::catalog::{ColumnDesc, ColumnId};
use risingwave_common::types::DataType;
use risingwave_connector::parser::{
ByteStreamSourceParserImpl, CommonParserConfig, ParserConfig, SpecificParserConfig,
@@ -37,15 +37,12 @@ use risingwave_connector::source::{
use tracing::Level;
use tracing_subscriber::prelude::*;
-static BATCH: LazyLock> = LazyLock::new(make_batch);
+static BATCH: LazyLock> = LazyLock::new(|| make_batch(false));
+static STRUCT_BATCH: LazyLock> = LazyLock::new(|| make_batch(true));
-fn make_batch() -> Vec {
+fn make_batch(use_struct: bool) -> Vec {
let mut generator = nexmark::EventGenerator::default()
.with_type_filter(nexmark::event::EventType::Bid)
- .map(|e| match e {
- nexmark::event::Event::Bid(bid) => bid, // extract the bid event
- _ => unreachable!(),
- })
.enumerate();
let message_base = SourceMessage {
@@ -59,8 +56,15 @@ fn make_batch() -> Vec {
generator
.by_ref()
.take(16384)
- .map(|(i, e)| {
- let payload = serde_json::to_vec(&e).unwrap();
+ .map(|(i, event)| {
+ let payload = if use_struct {
+ serde_json::to_vec(&event).unwrap()
+ } else {
+ let nexmark::event::Event::Bid(bid) = event else {
+ unreachable!()
+ };
+ serde_json::to_vec(&bid).unwrap()
+ };
SourceMessage {
payload: Some(payload),
offset: i.to_string(),
@@ -70,14 +74,18 @@ fn make_batch() -> Vec {
.collect_vec()
}
-fn make_data_stream() -> BoxSourceStream {
- futures::future::ready(Ok(BATCH.clone()))
- .into_stream()
- .boxed()
+fn make_data_stream(use_struct: bool) -> BoxSourceStream {
+ futures::future::ready(Ok(if use_struct {
+ STRUCT_BATCH.clone()
+ } else {
+ BATCH.clone()
+ }))
+ .into_stream()
+ .boxed()
}
-fn make_parser() -> ByteStreamSourceParserImpl {
- let rw_columns = [
+fn make_parser(use_struct: bool) -> ByteStreamSourceParserImpl {
+ let fields = vec![
("auction", DataType::Int64),
("bidder", DataType::Int64),
("price", DataType::Int64),
@@ -85,11 +93,23 @@ fn make_parser() -> ByteStreamSourceParserImpl {
("url", DataType::Varchar),
("date_time", DataType::Timestamp),
("extra", DataType::Varchar),
- ]
- .into_iter()
- .enumerate()
- .map(|(i, (n, t))| SourceColumnDesc::simple(n, t, ColumnId::new(i as _)))
- .collect_vec();
+ ];
+
+ let rw_columns = if use_struct {
+ let fields = fields
+ .into_iter()
+ .enumerate()
+ .map(|(i, (n, t))| ColumnDesc::named(n, ColumnId::new(i as _), t))
+ .collect();
+ let struct_col = ColumnDesc::new_struct("bid", 114514, "bid", fields);
+ vec![(&struct_col).into()]
+ } else {
+ fields
+ .into_iter()
+ .enumerate()
+ .map(|(i, (n, t))| SourceColumnDesc::simple(n, t, ColumnId::new(i as _)))
+ .collect_vec()
+ };
let config = ParserConfig {
common: CommonParserConfig { rw_columns },
@@ -99,8 +119,10 @@ fn make_parser() -> ByteStreamSourceParserImpl {
ByteStreamSourceParserImpl::create_for_test(config).unwrap()
}
-fn make_stream_iter() -> impl Iterator- {
- let mut stream: BoxChunkSourceStream = make_parser().into_stream(make_data_stream()).boxed();
+fn make_stream_iter(use_struct: bool) -> impl Iterator
- {
+ let mut stream: BoxChunkSourceStream = make_parser(use_struct)
+ .into_stream(make_data_stream(use_struct))
+ .boxed();
std::iter::from_fn(move || {
stream
@@ -116,7 +138,7 @@ fn make_stream_iter() -> impl Iterator
- {
fn bench(c: &mut Criterion) {
c.bench_function("parse_nexmark", |b| {
b.iter_batched(
- make_stream_iter,
+ || make_stream_iter(false),
|mut iter| iter.next().unwrap(),
BatchSize::SmallInput,
)
@@ -135,11 +157,19 @@ fn bench(c: &mut Criterion) {
.into();
b.iter_batched(
- make_stream_iter,
+ || make_stream_iter(false),
|mut iter| tracing::dispatcher::with_default(&dispatch, || iter.next().unwrap()),
BatchSize::SmallInput,
)
});
+
+ c.bench_function("parse_nexmark_struct_type", |b| {
+ b.iter_batched(
+ || make_stream_iter(true),
+ |mut iter| iter.next().unwrap(),
+ BatchSize::SmallInput,
+ )
+ });
}
criterion_group!(benches, bench);
diff --git a/src/connector/codec/src/decoder/avro/mod.rs b/src/connector/codec/src/decoder/avro/mod.rs
index e48eecfb7e2cf..cdd9aea416c8f 100644
--- a/src/connector/codec/src/decoder/avro/mod.rs
+++ b/src/connector/codec/src/decoder/avro/mod.rs
@@ -26,6 +26,7 @@ use risingwave_common::bail;
use risingwave_common::log::LogSuppresser;
use risingwave_common::types::{
DataType, Date, DatumCow, Interval, JsonbVal, ScalarImpl, Time, Timestamp, Timestamptz,
+ ToOwnedDatum,
};
use risingwave_common::util::iter_util::ZipEqFast;
@@ -56,7 +57,7 @@ impl<'a> AvroParseOptions<'a> {
}
impl<'a> AvroParseOptions<'a> {
- fn extract_inner_schema(&self, key: Option<&'a str>) -> Option<&'a Schema> {
+ fn extract_inner_schema(&self, key: Option<&str>) -> Option<&'a Schema> {
self.schema
.map(|schema| avro_extract_field_schema(schema, key))
.transpose()
@@ -87,8 +88,8 @@ impl<'a> AvroParseOptions<'a> {
pub fn convert_to_datum<'b>(
&self,
value: &'b Value,
- type_expected: &'b DataType,
- ) -> AccessResult
+ type_expected: &DataType,
+ ) -> AccessResult>
where
'b: 'a,
{
@@ -98,8 +99,14 @@ impl<'a> AvroParseOptions<'a> {
value: String::new(),
};
+ macro_rules! borrowed {
+ ($v:expr) => {
+ return Ok(DatumCow::Borrowed(Some($v.into())))
+ };
+ }
+
let v: ScalarImpl = match (type_expected, value) {
- (_, Value::Null) => return Ok(None),
+ (_, Value::Null) => return Ok(DatumCow::NULL),
(_, Value::Union(_, v)) => {
let schema = self.extract_inner_schema(None);
return Self {
@@ -183,8 +190,8 @@ impl<'a> AvroParseOptions<'a> {
.map_err(|_| create_error())?
.into(),
// ---- Varchar -----
- (DataType::Varchar, Value::Enum(_, symbol)) => symbol.clone().into_boxed_str().into(),
- (DataType::Varchar, Value::String(s)) => s.clone().into_boxed_str().into(),
+ (DataType::Varchar, Value::Enum(_, symbol)) => borrowed!(symbol.as_str()),
+ (DataType::Varchar, Value::String(s)) => borrowed!(s.as_str()),
// ---- Timestamp -----
(DataType::Timestamp, Value::LocalTimestampMillis(ms)) => Timestamp::with_millis(*ms)
.map_err(|_| create_error())?
@@ -223,7 +230,8 @@ impl<'a> AvroParseOptions<'a> {
schema,
relax_numeric: self.relax_numeric,
}
- .convert_to_datum(value, field_type)?)
+ .convert_to_datum(value, field_type)?
+ .to_owned_datum())
} else {
Ok(None)
}
@@ -247,7 +255,7 @@ impl<'a> AvroParseOptions<'a> {
})
.into(),
// ---- Bytea -----
- (DataType::Bytea, Value::Bytes(value)) => value.clone().into_boxed_slice().into(),
+ (DataType::Bytea, Value::Bytes(value)) => borrowed!(value.as_slice()),
// ---- Jsonb -----
(DataType::Jsonb, v @ Value::Map(_)) => {
let mut builder = jsonbb::Builder::default();
@@ -262,7 +270,7 @@ impl<'a> AvroParseOptions<'a> {
(_expected, _got) => Err(create_error())?,
};
- Ok(Some(v))
+ Ok(DatumCow::Owned(Some(v)))
}
}
@@ -308,10 +316,7 @@ impl Access for AvroAccess<'_> {
Err(create_error())?;
}
- // TODO: may borrow the value directly
- options
- .convert_to_datum(value, type_expected)
- .map(Into::into)
+ options.convert_to_datum(value, type_expected)
}
}
@@ -352,7 +357,7 @@ pub fn avro_schema_skip_union(schema: &Schema) -> anyhow::Result<&Schema> {
// extract inner filed/item schema of record/array/union
pub fn avro_extract_field_schema<'a>(
schema: &'a Schema,
- name: Option<&'a str>,
+ name: Option<&str>,
) -> anyhow::Result<&'a Schema> {
match schema {
Schema::Record(RecordSchema { fields, lookup, .. }) => {
@@ -524,9 +529,9 @@ mod tests {
value_schema: &Schema,
shape: &DataType,
) -> anyhow::Result {
- AvroParseOptions::create(value_schema)
- .convert_to_datum(&value, shape)
- .map_err(Into::into)
+ Ok(AvroParseOptions::create(value_schema)
+ .convert_to_datum(&value, shape)?
+ .to_owned_datum())
}
#[test]
@@ -569,7 +574,8 @@ mod tests {
let options = AvroParseOptions::create(&schema);
let resp = options
.convert_to_datum(&value, &DataType::Decimal)
- .unwrap();
+ .unwrap()
+ .to_owned_datum();
assert_eq!(
resp,
Some(ScalarImpl::Decimal(Decimal::Normalized(
@@ -608,7 +614,8 @@ mod tests {
let options = AvroParseOptions::create(&schema);
let resp = options
.convert_to_datum(&value, &DataType::Decimal)
- .unwrap();
+ .unwrap()
+ .to_owned_datum();
assert_eq!(resp, Some(ScalarImpl::Decimal(Decimal::from(66051))));
}
}
diff --git a/src/connector/src/parser/json_parser.rs b/src/connector/src/parser/json_parser.rs
index 9d62d76eff7a7..89f118eb1022f 100644
--- a/src/connector/src/parser/json_parser.rs
+++ b/src/connector/src/parser/json_parser.rs
@@ -26,6 +26,7 @@ use std::collections::BTreeMap;
use anyhow::Context as _;
use apache_avro::Schema;
use jst::{convert_avro, Context};
+use risingwave_connector_codec::decoder::avro::MapHandling;
use risingwave_pb::plan_common::ColumnDesc;
use super::util::{bytes_from_url, get_kafka_topic};
@@ -80,7 +81,7 @@ impl JsonAccessBuilder {
}
}
-pub async fn schema_to_columns(
+pub async fn fetch_json_schema_and_map_to_columns(
schema_location: &str,
schema_registry_auth: Option,
props: &BTreeMap,
@@ -98,11 +99,21 @@ pub async fn schema_to_columns(
let bytes = bytes_from_url(url, None).await?;
serde_json::from_slice(&bytes)?
};
- let context = Context::default();
- let avro_schema = convert_avro(&json_schema, context).to_string();
+ json_schema_to_columns(&json_schema)
+}
+
+/// FIXME: when the JSON schema is invalid, it will panic.
+///
+/// ## Notes on type conversion
+/// Map will be used when an object doesn't have `properties` but has `additionalProperties`.
+/// When an object has `properties` and `additionalProperties`, the latter will be ignored.
+///
+///
+/// TODO: examine other stuff like `oneOf`, `patternProperties`, etc.
+fn json_schema_to_columns(json_schema: &serde_json::Value) -> ConnectorResult> {
+ let avro_schema = convert_avro(json_schema, Context::default()).to_string();
let schema = Schema::parse_str(&avro_schema).context("failed to parse avro schema")?;
- // TODO: do we need to support map type here?
- avro_schema_to_column_descs(&schema, None).map_err(Into::into)
+ avro_schema_to_column_descs(&schema, Some(MapHandling::Jsonb)).map_err(Into::into)
}
#[cfg(test)]
diff --git a/src/connector/src/parser/mod.rs b/src/connector/src/parser/mod.rs
index d439da2491e6b..f7667a66a3747 100644
--- a/src/connector/src/parser/mod.rs
+++ b/src/connector/src/parser/mod.rs
@@ -30,7 +30,7 @@ use risingwave_common::bail;
use risingwave_common::catalog::{KAFKA_TIMESTAMP_COLUMN_NAME, TABLE_NAME_COLUMN_NAME};
use risingwave_common::log::LogSuppresser;
use risingwave_common::metrics::GLOBAL_ERROR_METRICS;
-use risingwave_common::types::{Datum, DatumCow, Scalar, ScalarImpl};
+use risingwave_common::types::{Datum, DatumCow, DatumRef, ScalarRefImpl};
use risingwave_common::util::iter_util::ZipEqFast;
use risingwave_common::util::tracing::InstrumentStream;
use risingwave_connector_codec::decoder::avro::MapHandling;
@@ -203,17 +203,17 @@ pub struct MessageMeta<'a> {
offset: &'a str,
}
-impl MessageMeta<'_> {
+impl<'a> MessageMeta<'a> {
/// Extract the value for the given column.
///
/// Returns `None` if the column is not a meta column.
- fn value_for_column(self, desc: &SourceColumnDesc) -> Option {
- match desc.column_type {
+ fn value_for_column(self, desc: &SourceColumnDesc) -> Option> {
+ let datum: DatumRef<'_> = match desc.column_type {
// Row id columns are filled with `NULL` here and will be filled with the real
// row id generated by `RowIdGenExecutor` later.
- SourceColumnType::RowId => Datum::None.into(),
+ SourceColumnType::RowId => None,
// Extract the offset from the meta data.
- SourceColumnType::Offset => Datum::Some(self.offset.into()).into(),
+ SourceColumnType::Offset => Some(self.offset.into()),
// Extract custom meta data per connector.
SourceColumnType::Meta if let SourceMeta::Kafka(kafka_meta) = self.meta => {
assert_eq!(
@@ -221,14 +221,11 @@ impl MessageMeta<'_> {
KAFKA_TIMESTAMP_COLUMN_NAME,
"unexpected kafka meta column name"
);
- kafka_meta
- .timestamp
- .map(|ts| {
- risingwave_common::cast::i64_to_timestamptz(ts)
- .unwrap()
- .to_scalar_value()
- })
- .into()
+ kafka_meta.timestamp.map(|ts| {
+ risingwave_common::cast::i64_to_timestamptz(ts)
+ .unwrap()
+ .into()
+ })
}
SourceColumnType::Meta if let SourceMeta::DebeziumCdc(cdc_meta) = self.meta => {
assert_eq!(
@@ -236,19 +233,21 @@ impl MessageMeta<'_> {
TABLE_NAME_COLUMN_NAME,
"unexpected cdc meta column name"
);
- Datum::Some(cdc_meta.full_table_name.as_str().into()).into()
+ Some(cdc_meta.full_table_name.as_str().into())
}
// For other cases, return `None`.
- SourceColumnType::Meta | SourceColumnType::Normal => None,
- }
+ SourceColumnType::Meta | SourceColumnType::Normal => return None,
+ };
+
+ Some(datum)
}
}
trait OpAction {
type Output<'a>;
- fn output_for<'a>(datum: Datum) -> Self::Output<'a>;
+ fn output_for<'a>(datum: impl Into>) -> Self::Output<'a>;
fn apply(builder: &mut ArrayBuilderImpl, output: Self::Output<'_>);
@@ -263,7 +262,7 @@ impl OpAction for OpActionInsert {
type Output<'a> = DatumCow<'a>;
#[inline(always)]
- fn output_for<'a>(datum: Datum) -> Self::Output<'a> {
+ fn output_for<'a>(datum: impl Into>) -> Self::Output<'a> {
datum.into()
}
@@ -289,7 +288,7 @@ impl OpAction for OpActionDelete {
type Output<'a> = DatumCow<'a>;
#[inline(always)]
- fn output_for<'a>(datum: Datum) -> Self::Output<'a> {
+ fn output_for<'a>(datum: impl Into>) -> Self::Output<'a> {
datum.into()
}
@@ -315,8 +314,9 @@ impl OpAction for OpActionUpdate {
type Output<'a> = (DatumCow<'a>, DatumCow<'a>);
#[inline(always)]
- fn output_for<'a>(datum: Datum) -> Self::Output<'a> {
- (datum.clone().into(), datum.into())
+ fn output_for<'a>(datum: impl Into>) -> Self::Output<'a> {
+ let datum = datum.into();
+ (datum.clone(), datum)
}
#[inline(always)]
@@ -345,7 +345,7 @@ impl SourceStreamChunkRowWriter<'_> {
}
fn do_action<'a, A: OpAction>(
- &mut self,
+ &'a mut self,
mut f: impl FnMut(&SourceColumnDesc) -> AccessResult>,
) -> AccessResult<()> {
let mut parse_field = |desc: &SourceColumnDesc| {
@@ -411,10 +411,11 @@ impl SourceStreamChunkRowWriter<'_> {
match self.row_meta {
Some(row_meta) => {
if let SourceMeta::DebeziumCdc(cdc_meta) = row_meta.meta {
- Ok(A::output_for(
- extract_cdc_meta_column(cdc_meta, col, desc.name.as_str())?
- .unwrap_or(None),
- ))
+ Ok(A::output_for(extract_cdc_meta_column(
+ cdc_meta,
+ col,
+ desc.name.as_str(),
+ )?))
} else {
Err(AccessError::Uncategorized {
message: "CDC metadata not found in the message".to_string(),
@@ -439,7 +440,7 @@ impl SourceStreamChunkRowWriter<'_> {
return Ok(A::output_for(
self.row_meta
.as_ref()
- .map(|ele| ScalarImpl::Utf8(ele.split_id.to_string().into())),
+ .map(|ele| ScalarRefImpl::Utf8(ele.split_id)),
));
}
(_, &Some(AdditionalColumnType::Offset(_))) => {
@@ -447,7 +448,7 @@ impl SourceStreamChunkRowWriter<'_> {
return Ok(A::output_for(
self.row_meta
.as_ref()
- .map(|ele| ScalarImpl::Utf8(ele.offset.to_string().into())),
+ .map(|ele| ScalarRefImpl::Utf8(ele.offset)),
));
}
(_, &Some(AdditionalColumnType::HeaderInner(ref header_inner))) => {
@@ -461,7 +462,7 @@ impl SourceStreamChunkRowWriter<'_> {
header_inner.data_type.as_ref(),
)
})
- .unwrap_or(None),
+ .unwrap_or(Datum::None.into()),
))
}
(_, &Some(AdditionalColumnType::Headers(_))) => {
@@ -477,7 +478,7 @@ impl SourceStreamChunkRowWriter<'_> {
return Ok(A::output_for(
self.row_meta
.as_ref()
- .map(|ele| ScalarImpl::Utf8(ele.split_id.to_string().into())),
+ .map(|ele| ScalarRefImpl::Utf8(ele.split_id)),
));
}
(_, _) => {
diff --git a/src/connector/src/parser/protobuf/parser.rs b/src/connector/src/parser/protobuf/parser.rs
index b5df0aeb83909..8be25074f6295 100644
--- a/src/connector/src/parser/protobuf/parser.rs
+++ b/src/connector/src/parser/protobuf/parser.rs
@@ -21,7 +21,10 @@ use prost_reflect::{
MessageDescriptor, ReflectMessage, Value,
};
use risingwave_common::array::{ListValue, StructValue};
-use risingwave_common::types::{DataType, Datum, Decimal, JsonbVal, ScalarImpl, F32, F64};
+use risingwave_common::types::{
+ DataType, Datum, DatumCow, Decimal, JsonbRef, JsonbVal, ScalarImpl, ScalarRefImpl, ToDatumRef,
+ ToOwnedDatum, F32, F64,
+};
use risingwave_common::{bail, try_match_expand};
use risingwave_pb::plan_common::{AdditionalColumn, ColumnDesc, ColumnDescVersion};
use thiserror::Error;
@@ -344,14 +347,20 @@ fn recursive_parse_json(
serde_json::Value::Object(ret)
}
-pub fn from_protobuf_value(
+pub fn from_protobuf_value<'a>(
field_desc: &FieldDescriptor,
- value: &Value,
+ value: &'a Value,
descriptor_pool: &Arc,
-) -> AccessResult {
+) -> AccessResult> {
let kind = field_desc.kind();
- let v = match value {
+ macro_rules! borrowed {
+ ($v:expr) => {
+ return Ok(DatumCow::Borrowed(Some($v.into())))
+ };
+ }
+
+ let v: ScalarImpl = match value {
Value::Bool(v) => ScalarImpl::Bool(*v),
Value::I32(i) => ScalarImpl::Int32(*i),
Value::U32(i) => ScalarImpl::Int64(*i as i64),
@@ -359,7 +368,7 @@ pub fn from_protobuf_value(
Value::U64(i) => ScalarImpl::Decimal(Decimal::from(*i)),
Value::F32(f) => ScalarImpl::Float32(F32::from(*f)),
Value::F64(f) => ScalarImpl::Float64(F64::from(*f)),
- Value::String(s) => ScalarImpl::Utf8(s.as_str().into()),
+ Value::String(s) => borrowed!(s.as_str()),
Value::EnumNumber(idx) => {
let enum_desc = kind.as_enum().ok_or_else(|| AccessError::TypeError {
expected: "enum".to_owned(),
@@ -375,9 +384,7 @@ pub fn from_protobuf_value(
if dyn_msg.descriptor().full_name() == "google.protobuf.Any" {
// If the fields are not presented, default value is an empty string
if !dyn_msg.has_field_by_name("type_url") || !dyn_msg.has_field_by_name("value") {
- return Ok(Some(ScalarImpl::Jsonb(JsonbVal::from(
- serde_json::json! {""},
- ))));
+ borrowed!(JsonbRef::empty_string());
}
// Sanity check
@@ -391,9 +398,8 @@ pub fn from_protobuf_value(
let payload_field_desc = dyn_msg.descriptor().get_field_by_name("value").unwrap();
- let Some(ScalarImpl::Bytea(payload)) =
- from_protobuf_value(&payload_field_desc, &payload, descriptor_pool)?
- else {
+ let payload = from_protobuf_value(&payload_field_desc, &payload, descriptor_pool)?;
+ let Some(ScalarRefImpl::Bytea(payload)) = payload.to_datum_ref() else {
bail_uncategorized!("expected bytes for dynamic message payload");
};
@@ -413,12 +419,13 @@ pub fn from_protobuf_value(
let full_name = msg_desc.clone().full_name().to_string();
// Decode the payload based on the `msg_desc`
- let decoded_value = DynamicMessage::decode(msg_desc, payload.as_ref()).unwrap();
+ let decoded_value = DynamicMessage::decode(msg_desc, payload).unwrap();
let decoded_value = from_protobuf_value(
field_desc,
&Value::Message(decoded_value),
descriptor_pool,
)?
+ .to_owned_datum()
.unwrap();
// Extract the struct value
@@ -447,7 +454,9 @@ pub fn from_protobuf_value(
}
// use default value if dyn_msg doesn't has this field
let value = dyn_msg.get_field(&field_desc);
- rw_values.push(from_protobuf_value(&field_desc, &value, descriptor_pool)?);
+ rw_values.push(
+ from_protobuf_value(&field_desc, &value, descriptor_pool)?.to_owned_datum(),
+ );
}
ScalarImpl::Struct(StructValue::new(rw_values))
}
@@ -461,14 +470,14 @@ pub fn from_protobuf_value(
}
ScalarImpl::List(ListValue::new(builder.finish()))
}
- Value::Bytes(value) => ScalarImpl::Bytea(value.to_vec().into_boxed_slice()),
+ Value::Bytes(value) => borrowed!(&**value),
_ => {
return Err(AccessError::UnsupportedType {
ty: format!("{kind:?}"),
});
}
};
- Ok(Some(v))
+ Ok(Some(v).into())
}
/// Maps protobuf type to RW type.
@@ -965,7 +974,9 @@ mod test {
let field = value.fields().next().unwrap().0;
if let Some(ret) =
- from_protobuf_value(&field, &Value::Message(value), &conf.descriptor_pool).unwrap()
+ from_protobuf_value(&field, &Value::Message(value), &conf.descriptor_pool)
+ .unwrap()
+ .to_owned_datum()
{
println!("Decoded Value for ANY_GEN_PROTO_DATA: {:#?}", ret);
println!("---------------------------");
@@ -1026,7 +1037,9 @@ mod test {
let field = value.fields().next().unwrap().0;
if let Some(ret) =
- from_protobuf_value(&field, &Value::Message(value), &conf.descriptor_pool).unwrap()
+ from_protobuf_value(&field, &Value::Message(value), &conf.descriptor_pool)
+ .unwrap()
+ .to_owned_datum()
{
println!("Decoded Value for ANY_GEN_PROTO_DATA: {:#?}", ret);
println!("---------------------------");
@@ -1098,7 +1111,9 @@ mod test {
let field = value.fields().next().unwrap().0;
if let Some(ret) =
- from_protobuf_value(&field, &Value::Message(value), &conf.descriptor_pool).unwrap()
+ from_protobuf_value(&field, &Value::Message(value), &conf.descriptor_pool)
+ .unwrap()
+ .to_owned_datum()
{
println!("Decoded Value for ANY_RECURSIVE_GEN_PROTO_DATA: {:#?}", ret);
println!("---------------------------");
diff --git a/src/connector/src/parser/unified/json.rs b/src/connector/src/parser/unified/json.rs
index fdf61c581b731..09704d9192a41 100644
--- a/src/connector/src/parser/unified/json.rs
+++ b/src/connector/src/parser/unified/json.rs
@@ -22,8 +22,8 @@ use risingwave_common::array::{ListValue, StructValue};
use risingwave_common::cast::{i64_to_timestamp, i64_to_timestamptz, str_to_bytea};
use risingwave_common::log::LogSuppresser;
use risingwave_common::types::{
- DataType, Date, Datum, Decimal, Int256, Interval, JsonbVal, ScalarImpl, Time, Timestamp,
- Timestamptz, ToOwnedDatum,
+ DataType, Date, Decimal, Int256, Interval, JsonbVal, ScalarImpl, Time, Timestamp, Timestamptz,
+ ToOwnedDatum,
};
use risingwave_common::util::iter_util::ZipEqFast;
use risingwave_connector_codec::decoder::utils::extract_decimal;
@@ -213,7 +213,7 @@ impl JsonParseOptions {
};
let v: ScalarImpl = match (type_expected, value.value_type()) {
- (_, ValueType::Null) => return Ok(Datum::None.into()),
+ (_, ValueType::Null) => return Ok(DatumCow::NULL),
// ---- Boolean -----
(DataType::Boolean, ValueType::Bool) => value.as_bool().unwrap().into(),
diff --git a/src/connector/src/parser/unified/protobuf.rs b/src/connector/src/parser/unified/protobuf.rs
index 4bea2cbab306b..02febc22db247 100644
--- a/src/connector/src/parser/unified/protobuf.rs
+++ b/src/connector/src/parser/unified/protobuf.rs
@@ -12,11 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+use std::borrow::Cow;
use std::sync::{Arc, LazyLock};
use prost_reflect::{DescriptorPool, DynamicMessage, ReflectMessage};
use risingwave_common::log::LogSuppresser;
-use risingwave_common::types::{DataType, DatumCow};
+use risingwave_common::types::{DataType, DatumCow, ToOwnedDatum};
use thiserror_ext::AsReport;
use super::{Access, AccessResult};
@@ -56,9 +57,14 @@ impl Access for ProtobufAccess {
tracing::error!(suppressed_count, "{}", e.as_report());
}
})?;
- let value = self.message.get_field(&field_desc);
- // TODO: may borrow the value directly
- from_protobuf_value(&field_desc, &value, &self.descriptor_pool).map(Into::into)
+ match self.message.get_field(&field_desc) {
+ Cow::Borrowed(value) => from_protobuf_value(&field_desc, value, &self.descriptor_pool),
+
+ // `Owned` variant occurs only if there's no such field and the default value is returned.
+ Cow::Owned(value) => from_protobuf_value(&field_desc, &value, &self.descriptor_pool)
+ // enforce `Owned` variant to avoid returning a reference to a temporary value
+ .map(|d| d.to_owned_datum().into()),
+ }
}
}
diff --git a/src/connector/src/parser/util.rs b/src/connector/src/parser/util.rs
index 4afbbb718d54a..30cb1fbf7d62e 100644
--- a/src/connector/src/parser/util.rs
+++ b/src/connector/src/parser/util.rs
@@ -17,7 +17,7 @@ use anyhow::Context;
use bytes::Bytes;
use reqwest::Url;
use risingwave_common::bail;
-use risingwave_common::types::Datum;
+use risingwave_common::types::{Datum, DatumCow, DatumRef};
use risingwave_pb::data::DataType as PbDataType;
use crate::aws_utils::load_file_descriptor_from_s3;
@@ -132,19 +132,19 @@ pub(super) async fn bytes_from_url(
}
}
-pub fn extreact_timestamp_from_meta(meta: &SourceMeta) -> Option {
+pub fn extreact_timestamp_from_meta(meta: &SourceMeta) -> Option> {
match meta {
SourceMeta::Kafka(kafka_meta) => kafka_meta.extract_timestamp(),
- SourceMeta::DebeziumCdc(cdc_meta) => cdc_meta.extract_timestamp(),
+ SourceMeta::DebeziumCdc(cdc_meta) => Some(cdc_meta.extract_timestamp()),
_ => None,
}
}
-pub fn extract_cdc_meta_column(
- cdc_meta: &DebeziumCdcMeta,
+pub fn extract_cdc_meta_column<'a>(
+ cdc_meta: &'a DebeziumCdcMeta,
column_type: &additional_column::ColumnType,
column_name: &str,
-) -> AccessResult