Compare commits

...

5 Commits

Author SHA1 Message Date
evenyag
ab1928d5fd feat: refetch sst on open 2025-03-17 15:17:14 +08:00
Sicong Hu
09dacc8e9b feat: add vec_subvector function (#5683)
* feat: add vec_subvector function

* change datatype of arg1 and arg2 from u64 to i64

* add sqlness test

* improve description comments
2025-03-16 10:43:53 +00:00
Ruihang Xia
dec439db2b chore: bump version to 0.14.0 (#5711)
Signed-off-by: Ruihang Xia <waynestxia@gmail.com>
2025-03-16 09:58:19 +00:00
Ning Sun
dc76571166 feat: move default data path from /tmp to current directory (#5719) 2025-03-16 09:57:46 +00:00
shuiyisong
3e17f8c426 chore: use Bytes instead of string in bulk ingestion (#5717)
chore: use bytes instead of string in bulk log ingestion
2025-03-14 09:31:35 +00:00
31 changed files with 635 additions and 164 deletions

View File

@@ -91,7 +91,7 @@ env:
# The scheduled version is '${{ env.NEXT_RELEASE_VERSION }}-nightly-YYYYMMDD', like v0.2.0-nigthly-20230313;
NIGHTLY_RELEASE_PREFIX: nightly
# Note: The NEXT_RELEASE_VERSION should be modified manually by every formal release.
NEXT_RELEASE_VERSION: v0.13.0
NEXT_RELEASE_VERSION: v0.14.0
jobs:
allocate-runners:

3
.gitignore vendored
View File

@@ -54,3 +54,6 @@ tests-fuzz/corpus/
# Nix
.direnv
.envrc
## default data home
greptimedb_data

142
Cargo.lock generated
View File

@@ -185,7 +185,7 @@ checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c"
[[package]]
name = "api"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"common-base",
"common-decimal",
@@ -710,7 +710,7 @@ dependencies = [
[[package]]
name = "auth"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"async-trait",
@@ -1324,7 +1324,7 @@ dependencies = [
[[package]]
name = "cache"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"catalog",
"common-error",
@@ -1348,7 +1348,7 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "catalog"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"arrow",
@@ -1661,7 +1661,7 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
[[package]]
name = "cli"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"async-trait",
"auth",
@@ -1704,7 +1704,7 @@ dependencies = [
"session",
"snafu 0.8.5",
"store-api",
"substrait 0.13.0",
"substrait 0.14.0",
"table",
"tempfile",
"tokio",
@@ -1713,7 +1713,7 @@ dependencies = [
[[package]]
name = "client"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"arc-swap",
@@ -1740,7 +1740,7 @@ dependencies = [
"rand",
"serde_json",
"snafu 0.8.5",
"substrait 0.13.0",
"substrait 0.14.0",
"substrait 0.37.3",
"tokio",
"tokio-stream",
@@ -1781,7 +1781,7 @@ dependencies = [
[[package]]
name = "cmd"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"async-trait",
"auth",
@@ -1842,7 +1842,7 @@ dependencies = [
"similar-asserts",
"snafu 0.8.5",
"store-api",
"substrait 0.13.0",
"substrait 0.14.0",
"table",
"temp-env",
"tempfile",
@@ -1888,7 +1888,7 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335"
[[package]]
name = "common-base"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"anymap2",
"async-trait",
@@ -1910,11 +1910,11 @@ dependencies = [
[[package]]
name = "common-catalog"
version = "0.13.0"
version = "0.14.0"
[[package]]
name = "common-config"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"common-base",
"common-error",
@@ -1939,7 +1939,7 @@ dependencies = [
[[package]]
name = "common-datasource"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"arrow",
"arrow-schema",
@@ -1975,7 +1975,7 @@ dependencies = [
[[package]]
name = "common-decimal"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"bigdecimal 0.4.5",
"common-error",
@@ -1988,7 +1988,7 @@ dependencies = [
[[package]]
name = "common-error"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"http 1.1.0",
"snafu 0.8.5",
@@ -1998,7 +1998,7 @@ dependencies = [
[[package]]
name = "common-frontend"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"async-trait",
"common-error",
@@ -2008,7 +2008,7 @@ dependencies = [
[[package]]
name = "common-function"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"ahash 0.8.11",
"api",
@@ -2059,7 +2059,7 @@ dependencies = [
[[package]]
name = "common-greptimedb-telemetry"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"async-trait",
"common-runtime",
@@ -2076,7 +2076,7 @@ dependencies = [
[[package]]
name = "common-grpc"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"arrow-flight",
@@ -2104,7 +2104,7 @@ dependencies = [
[[package]]
name = "common-grpc-expr"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"common-base",
@@ -2123,7 +2123,7 @@ dependencies = [
[[package]]
name = "common-macro"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"arc-swap",
"common-query",
@@ -2137,7 +2137,7 @@ dependencies = [
[[package]]
name = "common-mem-prof"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"common-error",
"common-macro",
@@ -2150,7 +2150,7 @@ dependencies = [
[[package]]
name = "common-meta"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"anymap2",
"api",
@@ -2211,7 +2211,7 @@ dependencies = [
[[package]]
name = "common-options"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"common-grpc",
"humantime-serde",
@@ -2220,11 +2220,11 @@ dependencies = [
[[package]]
name = "common-plugins"
version = "0.13.0"
version = "0.14.0"
[[package]]
name = "common-pprof"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"common-error",
"common-macro",
@@ -2236,7 +2236,7 @@ dependencies = [
[[package]]
name = "common-procedure"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"async-stream",
"async-trait",
@@ -2263,7 +2263,7 @@ dependencies = [
[[package]]
name = "common-procedure-test"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"async-trait",
"common-procedure",
@@ -2271,7 +2271,7 @@ dependencies = [
[[package]]
name = "common-query"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"async-trait",
@@ -2297,7 +2297,7 @@ dependencies = [
[[package]]
name = "common-recordbatch"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"arc-swap",
"common-error",
@@ -2316,7 +2316,7 @@ dependencies = [
[[package]]
name = "common-runtime"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"async-trait",
"clap 4.5.19",
@@ -2346,7 +2346,7 @@ dependencies = [
[[package]]
name = "common-telemetry"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"atty",
"backtrace",
@@ -2374,7 +2374,7 @@ dependencies = [
[[package]]
name = "common-test-util"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"client",
"common-query",
@@ -2386,7 +2386,7 @@ dependencies = [
[[package]]
name = "common-time"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"arrow",
"chrono",
@@ -2404,7 +2404,7 @@ dependencies = [
[[package]]
name = "common-version"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"build-data",
"const_format",
@@ -2414,7 +2414,7 @@ dependencies = [
[[package]]
name = "common-wal"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"common-base",
"common-error",
@@ -3345,7 +3345,7 @@ dependencies = [
[[package]]
name = "datanode"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"arrow-flight",
@@ -3397,7 +3397,7 @@ dependencies = [
"session",
"snafu 0.8.5",
"store-api",
"substrait 0.13.0",
"substrait 0.14.0",
"table",
"tokio",
"toml 0.8.19",
@@ -3406,7 +3406,7 @@ dependencies = [
[[package]]
name = "datatypes"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"arrow",
"arrow-array",
@@ -4050,7 +4050,7 @@ dependencies = [
[[package]]
name = "file-engine"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"async-trait",
@@ -4161,7 +4161,7 @@ checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8"
[[package]]
name = "flow"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"arrow",
@@ -4223,7 +4223,7 @@ dependencies = [
"snafu 0.8.5",
"store-api",
"strum 0.25.0",
"substrait 0.13.0",
"substrait 0.14.0",
"table",
"tokio",
"tonic 0.12.3",
@@ -4278,7 +4278,7 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa"
[[package]]
name = "frontend"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"arc-swap",
@@ -5546,7 +5546,7 @@ dependencies = [
[[package]]
name = "index"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"async-trait",
"asynchronous-codec",
@@ -6348,7 +6348,7 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "log-query"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"chrono",
"common-error",
@@ -6360,7 +6360,7 @@ dependencies = [
[[package]]
name = "log-store"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"async-stream",
"async-trait",
@@ -6653,7 +6653,7 @@ dependencies = [
[[package]]
name = "meta-client"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"async-trait",
@@ -6680,7 +6680,7 @@ dependencies = [
[[package]]
name = "meta-srv"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"async-trait",
@@ -6767,7 +6767,7 @@ dependencies = [
[[package]]
name = "metric-engine"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"aquamarine",
@@ -6865,7 +6865,7 @@ dependencies = [
[[package]]
name = "mito2"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"aquamarine",
@@ -7562,7 +7562,7 @@ dependencies = [
[[package]]
name = "object-store"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"anyhow",
"bytes",
@@ -7811,7 +7811,7 @@ dependencies = [
[[package]]
name = "operator"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"ahash 0.8.11",
"api",
@@ -7859,7 +7859,7 @@ dependencies = [
"sql",
"sqlparser 0.52.0 (git+https://github.com/GreptimeTeam/sqlparser-rs.git?rev=71dd86058d2af97b9925093d40c4e03360403170)",
"store-api",
"substrait 0.13.0",
"substrait 0.14.0",
"table",
"tokio",
"tokio-util",
@@ -8096,7 +8096,7 @@ dependencies = [
[[package]]
name = "partition"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"async-trait",
@@ -8364,7 +8364,7 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pipeline"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"ahash 0.8.11",
"api",
@@ -8504,7 +8504,7 @@ dependencies = [
[[package]]
name = "plugins"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"auth",
"clap 4.5.19",
@@ -8766,7 +8766,7 @@ dependencies = [
[[package]]
name = "promql"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"ahash 0.8.11",
"async-trait",
@@ -9013,7 +9013,7 @@ dependencies = [
[[package]]
name = "puffin"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"async-compression 0.4.13",
"async-trait",
@@ -9054,7 +9054,7 @@ dependencies = [
[[package]]
name = "query"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"ahash 0.8.11",
"api",
@@ -9119,7 +9119,7 @@ dependencies = [
"sqlparser 0.52.0 (git+https://github.com/GreptimeTeam/sqlparser-rs.git?rev=71dd86058d2af97b9925093d40c4e03360403170)",
"statrs",
"store-api",
"substrait 0.13.0",
"substrait 0.14.0",
"table",
"tokio",
"tokio-stream",
@@ -10474,7 +10474,7 @@ dependencies = [
[[package]]
name = "servers"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"ahash 0.8.11",
"api",
@@ -10591,7 +10591,7 @@ dependencies = [
[[package]]
name = "session"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"arc-swap",
@@ -10900,7 +10900,7 @@ dependencies = [
[[package]]
name = "sql"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"chrono",
@@ -10954,7 +10954,7 @@ dependencies = [
[[package]]
name = "sqlness-runner"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"async-trait",
"clap 4.5.19",
@@ -11271,7 +11271,7 @@ dependencies = [
[[package]]
name = "store-api"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"aquamarine",
@@ -11401,7 +11401,7 @@ dependencies = [
[[package]]
name = "substrait"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"async-trait",
"bytes",
@@ -11582,7 +11582,7 @@ dependencies = [
[[package]]
name = "table"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"async-trait",
@@ -11833,7 +11833,7 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
[[package]]
name = "tests-fuzz"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"arbitrary",
"async-trait",
@@ -11877,7 +11877,7 @@ dependencies = [
[[package]]
name = "tests-integration"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"api",
"arrow-flight",
@@ -11943,7 +11943,7 @@ dependencies = [
"sql",
"sqlx",
"store-api",
"substrait 0.13.0",
"substrait 0.14.0",
"table",
"tempfile",
"time",

View File

@@ -67,7 +67,7 @@ members = [
resolver = "2"
[workspace.package]
version = "0.13.0"
version = "0.14.0"
edition = "2021"
license = "Apache-2.0"

View File

@@ -112,7 +112,7 @@ Start a GreptimeDB container with:
```shell
docker run -p 127.0.0.1:4000-4003:4000-4003 \
-v "$(pwd)/greptimedb:/tmp/greptimedb" \
-v "$(pwd)/greptimedb:./greptimedb_data" \
--name greptime --rm \
greptime/greptimedb:latest standalone start \
--http-addr 0.0.0.0:4000 \

View File

@@ -101,7 +101,7 @@
| `flow` | -- | -- | flow engine options. |
| `flow.num_workers` | Integer | `0` | The number of flow worker in flownode.<br/>Not setting(or set to 0) this value will use the number of CPU cores divided by 2. |
| `storage` | -- | -- | The data storage options. |
| `storage.data_home` | String | `/tmp/greptimedb/` | The working home directory. |
| `storage.data_home` | String | `./greptimedb_data/` | The working home directory. |
| `storage.type` | String | `File` | The storage type used to store the data.<br/>- `File`: the data is stored in the local file system.<br/>- `S3`: the data is stored in the S3 object storage.<br/>- `Gcs`: the data is stored in the Google Cloud Storage.<br/>- `Azblob`: the data is stored in the Azure Blob Storage.<br/>- `Oss`: the data is stored in the Aliyun OSS. |
| `storage.cache_path` | String | Unset | Read cache configuration for object storage such as 'S3' etc, it's configured by default when using object storage. It is recommended to configure it when using object storage for better performance.<br/>A local file directory, defaults to `{data_home}`. An empty string means disabling. |
| `storage.cache_capacity` | String | Unset | The local file cache capacity in bytes. If your disk space is sufficient, it is recommended to set it larger. |
@@ -181,7 +181,7 @@
| `region_engine.metric` | -- | -- | Metric engine options. |
| `region_engine.metric.experimental_sparse_primary_key_encoding` | Bool | `false` | Whether to enable the experimental sparse primary key encoding. |
| `logging` | -- | -- | The logging options. |
| `logging.dir` | String | `/tmp/greptimedb/logs` | The directory to store the log files. If set to empty, logs will not be written to files. |
| `logging.dir` | String | `./greptimedb_data/logs` | The directory to store the log files. If set to empty, logs will not be written to files. |
| `logging.level` | String | Unset | The log level. Can be `info`/`debug`/`warn`/`error`. |
| `logging.enable_otlp_tracing` | Bool | `false` | Enable OTLP tracing. |
| `logging.otlp_endpoint` | String | `http://localhost:4317` | The OTLP tracing endpoint. |
@@ -279,7 +279,7 @@
| `datanode.client.connect_timeout` | String | `10s` | -- |
| `datanode.client.tcp_nodelay` | Bool | `true` | -- |
| `logging` | -- | -- | The logging options. |
| `logging.dir` | String | `/tmp/greptimedb/logs` | The directory to store the log files. If set to empty, logs will not be written to files. |
| `logging.dir` | String | `./greptimedb_data/logs` | The directory to store the log files. If set to empty, logs will not be written to files. |
| `logging.level` | String | Unset | The log level. Can be `info`/`debug`/`warn`/`error`. |
| `logging.enable_otlp_tracing` | Bool | `false` | Enable OTLP tracing. |
| `logging.otlp_endpoint` | String | `http://localhost:4317` | The OTLP tracing endpoint. |
@@ -308,7 +308,7 @@
| Key | Type | Default | Descriptions |
| --- | -----| ------- | ----------- |
| `data_home` | String | `/tmp/metasrv/` | The working home directory. |
| `data_home` | String | `./greptimedb_data/metasrv/` | The working home directory. |
| `bind_addr` | String | `127.0.0.1:3002` | The bind address of metasrv. |
| `server_addr` | String | `127.0.0.1:3002` | The communication server address for the frontend and datanode to connect to metasrv.<br/>If left empty or unset, the server will automatically use the IP address of the first network interface<br/>on the host, with the same port number as the one specified in `bind_addr`. |
| `store_addrs` | Array | -- | Store server address default to etcd store.<br/>For postgres store, the format is:<br/>"password=password dbname=postgres user=postgres host=localhost port=5432"<br/>For etcd store, the format is:<br/>"127.0.0.1:2379" |
@@ -352,7 +352,7 @@
| `wal.backoff_base` | Integer | `2` | Exponential backoff rate, i.e. next backoff = base * current backoff. |
| `wal.backoff_deadline` | String | `5mins` | Stop reconnecting if the total wait time reaches the deadline. If this config is missing, the reconnecting won't terminate. |
| `logging` | -- | -- | The logging options. |
| `logging.dir` | String | `/tmp/greptimedb/logs` | The directory to store the log files. If set to empty, logs will not be written to files. |
| `logging.dir` | String | `./greptimedb_data/logs` | The directory to store the log files. If set to empty, logs will not be written to files. |
| `logging.level` | String | Unset | The log level. Can be `info`/`debug`/`warn`/`error`. |
| `logging.enable_otlp_tracing` | Bool | `false` | Enable OTLP tracing. |
| `logging.otlp_endpoint` | String | `http://localhost:4317` | The OTLP tracing endpoint. |
@@ -442,7 +442,7 @@
| `wal.dump_index_interval` | String | `60s` | The interval for dumping WAL indexes.<br/>**It's only used when the provider is `kafka`**. |
| `wal.overwrite_entry_start_id` | Bool | `false` | Ignore missing entries during read WAL.<br/>**It's only used when the provider is `kafka`**.<br/><br/>This option ensures that when Kafka messages are deleted, the system<br/>can still successfully replay memtable data without throwing an<br/>out-of-range error.<br/>However, enabling this option might lead to unexpected data loss,<br/>as the system will skip over missing entries instead of treating<br/>them as critical errors. |
| `storage` | -- | -- | The data storage options. |
| `storage.data_home` | String | `/tmp/greptimedb/` | The working home directory. |
| `storage.data_home` | String | `./greptimedb_data/` | The working home directory. |
| `storage.type` | String | `File` | The storage type used to store the data.<br/>- `File`: the data is stored in the local file system.<br/>- `S3`: the data is stored in the S3 object storage.<br/>- `Gcs`: the data is stored in the Google Cloud Storage.<br/>- `Azblob`: the data is stored in the Azure Blob Storage.<br/>- `Oss`: the data is stored in the Aliyun OSS. |
| `storage.cache_path` | String | Unset | Read cache configuration for object storage such as 'S3' etc, it's configured by default when using object storage. It is recommended to configure it when using object storage for better performance.<br/>A local file directory, defaults to `{data_home}`. An empty string means disabling. |
| `storage.cache_capacity` | String | Unset | The local file cache capacity in bytes. If your disk space is sufficient, it is recommended to set it larger. |
@@ -522,7 +522,7 @@
| `region_engine.metric` | -- | -- | Metric engine options. |
| `region_engine.metric.experimental_sparse_primary_key_encoding` | Bool | `false` | Whether to enable the experimental sparse primary key encoding. |
| `logging` | -- | -- | The logging options. |
| `logging.dir` | String | `/tmp/greptimedb/logs` | The directory to store the log files. If set to empty, logs will not be written to files. |
| `logging.dir` | String | `./greptimedb_data/logs` | The directory to store the log files. If set to empty, logs will not be written to files. |
| `logging.level` | String | Unset | The log level. Can be `info`/`debug`/`warn`/`error`. |
| `logging.enable_otlp_tracing` | Bool | `false` | Enable OTLP tracing. |
| `logging.otlp_endpoint` | String | `http://localhost:4317` | The OTLP tracing endpoint. |
@@ -579,7 +579,7 @@
| `heartbeat.interval` | String | `3s` | Interval for sending heartbeat messages to the metasrv. |
| `heartbeat.retry_interval` | String | `3s` | Interval for retrying to send heartbeat messages to the metasrv. |
| `logging` | -- | -- | The logging options. |
| `logging.dir` | String | `/tmp/greptimedb/logs` | The directory to store the log files. If set to empty, logs will not be written to files. |
| `logging.dir` | String | `./greptimedb_data/logs` | The directory to store the log files. If set to empty, logs will not be written to files. |
| `logging.level` | String | Unset | The log level. Can be `info`/`debug`/`warn`/`error`. |
| `logging.enable_otlp_tracing` | Bool | `false` | Enable OTLP tracing. |
| `logging.otlp_endpoint` | String | `http://localhost:4317` | The OTLP tracing endpoint. |

View File

@@ -119,7 +119,7 @@ provider = "raft_engine"
## The directory to store the WAL files.
## **It's only used when the provider is `raft_engine`**.
## @toml2docs:none-default
dir = "/tmp/greptimedb/wal"
dir = "./greptimedb_data/wal"
## The size of the WAL segment file.
## **It's only used when the provider is `raft_engine`**.
@@ -265,7 +265,7 @@ overwrite_entry_start_id = false
## The data storage options.
[storage]
## The working home directory.
data_home = "/tmp/greptimedb/"
data_home = "./greptimedb_data/"
## The storage type used to store the data.
## - `File`: the data is stored in the local file system.
@@ -618,7 +618,7 @@ experimental_sparse_primary_key_encoding = false
## The logging options.
[logging]
## The directory to store the log files. If set to empty, logs will not be written to files.
dir = "/tmp/greptimedb/logs"
dir = "./greptimedb_data/logs"
## The log level. Can be `info`/`debug`/`warn`/`error`.
## @toml2docs:none-default

View File

@@ -76,7 +76,7 @@ retry_interval = "3s"
## The logging options.
[logging]
## The directory to store the log files. If set to empty, logs will not be written to files.
dir = "/tmp/greptimedb/logs"
dir = "./greptimedb_data/logs"
## The log level. Can be `info`/`debug`/`warn`/`error`.
## @toml2docs:none-default
@@ -121,4 +121,3 @@ sample_ratio = 1.0
## The tokio console address.
## @toml2docs:none-default
#+ tokio_console_addr = "127.0.0.1"

View File

@@ -189,7 +189,7 @@ tcp_nodelay = true
## The logging options.
[logging]
## The directory to store the log files. If set to empty, logs will not be written to files.
dir = "/tmp/greptimedb/logs"
dir = "./greptimedb_data/logs"
## The log level. Can be `info`/`debug`/`warn`/`error`.
## @toml2docs:none-default

View File

@@ -1,5 +1,5 @@
## The working home directory.
data_home = "/tmp/metasrv/"
data_home = "./greptimedb_data/metasrv/"
## The bind address of metasrv.
bind_addr = "127.0.0.1:3002"
@@ -177,7 +177,7 @@ backoff_deadline = "5mins"
## The logging options.
[logging]
## The directory to store the log files. If set to empty, logs will not be written to files.
dir = "/tmp/greptimedb/logs"
dir = "./greptimedb_data/logs"
## The log level. Can be `info`/`debug`/`warn`/`error`.
## @toml2docs:none-default

View File

@@ -164,7 +164,7 @@ provider = "raft_engine"
## The directory to store the WAL files.
## **It's only used when the provider is `raft_engine`**.
## @toml2docs:none-default
dir = "/tmp/greptimedb/wal"
dir = "./greptimedb_data/wal"
## The size of the WAL segment file.
## **It's only used when the provider is `raft_engine`**.
@@ -352,7 +352,7 @@ retry_delay = "500ms"
## The data storage options.
[storage]
## The working home directory.
data_home = "/tmp/greptimedb/"
data_home = "./greptimedb_data/"
## The storage type used to store the data.
## - `File`: the data is stored in the local file system.
@@ -705,7 +705,7 @@ experimental_sparse_primary_key_encoding = false
## The logging options.
[logging]
## The directory to store the log files. If set to empty, logs will not be written to files.
dir = "/tmp/greptimedb/logs"
dir = "./greptimedb_data/logs"
## The log level. Can be `info`/`debug`/`warn`/`error`.
## @toml2docs:none-default

View File

@@ -25,7 +25,7 @@ services:
- --initial-cluster-state=new
- *etcd_initial_cluster_token
volumes:
- /tmp/greptimedb-cluster-docker-compose/etcd0:/var/lib/etcd
- ./greptimedb-cluster-docker-compose/etcd0:/var/lib/etcd
healthcheck:
test: [ "CMD", "etcdctl", "--endpoints=http://etcd0:2379", "endpoint", "health" ]
interval: 5s
@@ -68,12 +68,13 @@ services:
- datanode
- start
- --node-id=0
- --data-home=/greptimedb_data
- --rpc-bind-addr=0.0.0.0:3001
- --rpc-server-addr=datanode0:3001
- --metasrv-addrs=metasrv:3002
- --http-addr=0.0.0.0:5000
volumes:
- /tmp/greptimedb-cluster-docker-compose/datanode0:/tmp/greptimedb
- ./greptimedb-cluster-docker-compose/datanode0:/greptimedb_data
healthcheck:
test: [ "CMD", "curl", "-fv", "http://datanode0:5000/health" ]
interval: 5s

View File

@@ -406,7 +406,7 @@ mod tests {
sync_write = false
[storage]
data_home = "/tmp/greptimedb/"
data_home = "./greptimedb_data/"
type = "File"
[[storage.providers]]
@@ -420,7 +420,7 @@ mod tests {
[logging]
level = "debug"
dir = "/tmp/greptimedb/test/logs"
dir = "./greptimedb_data/test/logs"
"#;
write!(file, "{}", toml_str).unwrap();
@@ -467,7 +467,7 @@ mod tests {
assert_eq!(10000, ddl_timeout.as_millis());
assert_eq!(3000, timeout.as_millis());
assert!(tcp_nodelay);
assert_eq!("/tmp/greptimedb/", options.storage.data_home);
assert_eq!("./greptimedb_data/", options.storage.data_home);
assert!(matches!(
&options.storage.store,
ObjectStoreConfig::File(FileConfig { .. })
@@ -483,7 +483,10 @@ mod tests {
));
assert_eq!("debug", options.logging.level.unwrap());
assert_eq!("/tmp/greptimedb/test/logs".to_string(), options.logging.dir);
assert_eq!(
"./greptimedb_data/test/logs".to_string(),
options.logging.dir
);
}
#[test]
@@ -526,7 +529,7 @@ mod tests {
let options = cmd
.load_options(&GlobalOptions {
log_dir: Some("/tmp/greptimedb/test/logs".to_string()),
log_dir: Some("./greptimedb_data/test/logs".to_string()),
log_level: Some("debug".to_string()),
#[cfg(feature = "tokio-console")]
@@ -536,7 +539,7 @@ mod tests {
.component;
let logging_opt = options.logging;
assert_eq!("/tmp/greptimedb/test/logs", logging_opt.dir);
assert_eq!("./greptimedb_data/test/logs", logging_opt.dir);
assert_eq!("debug", logging_opt.level.as_ref().unwrap());
}
@@ -565,11 +568,11 @@ mod tests {
[storage]
type = "File"
data_home = "/tmp/greptimedb/"
data_home = "./greptimedb_data/"
[logging]
level = "debug"
dir = "/tmp/greptimedb/test/logs"
dir = "./greptimedb_data/test/logs"
"#;
write!(file, "{}", toml_str).unwrap();

View File

@@ -448,7 +448,7 @@ mod tests {
[logging]
level = "debug"
dir = "/tmp/greptimedb/test/logs"
dir = "./greptimedb_data/test/logs"
"#;
write!(file, "{}", toml_str).unwrap();
@@ -466,7 +466,10 @@ mod tests {
assert_eq!(ReadableSize::gb(2), fe_opts.http.body_limit);
assert_eq!("debug", fe_opts.logging.level.as_ref().unwrap());
assert_eq!("/tmp/greptimedb/test/logs".to_string(), fe_opts.logging.dir);
assert_eq!(
"./greptimedb_data/test/logs".to_string(),
fe_opts.logging.dir
);
assert!(!fe_opts.opentsdb.enable);
}
@@ -505,7 +508,7 @@ mod tests {
let options = cmd
.load_options(&GlobalOptions {
log_dir: Some("/tmp/greptimedb/test/logs".to_string()),
log_dir: Some("./greptimedb_data/test/logs".to_string()),
log_level: Some("debug".to_string()),
#[cfg(feature = "tokio-console")]
@@ -515,7 +518,7 @@ mod tests {
.component;
let logging_opt = options.logging;
assert_eq!("/tmp/greptimedb/test/logs", logging_opt.dir);
assert_eq!("./greptimedb_data/test/logs", logging_opt.dir);
assert_eq!("debug", logging_opt.level.as_ref().unwrap());
}

View File

@@ -337,7 +337,7 @@ mod tests {
[logging]
level = "debug"
dir = "/tmp/greptimedb/test/logs"
dir = "./greptimedb_data/test/logs"
[failure_detector]
threshold = 8.0
@@ -358,7 +358,10 @@ mod tests {
assert_eq!(vec!["127.0.0.1:2379".to_string()], options.store_addrs);
assert_eq!(SelectorType::LeaseBased, options.selector);
assert_eq!("debug", options.logging.level.as_ref().unwrap());
assert_eq!("/tmp/greptimedb/test/logs".to_string(), options.logging.dir);
assert_eq!(
"./greptimedb_data/test/logs".to_string(),
options.logging.dir
);
assert_eq!(8.0, options.failure_detector.threshold);
assert_eq!(
100.0,
@@ -396,7 +399,7 @@ mod tests {
let options = cmd
.load_options(&GlobalOptions {
log_dir: Some("/tmp/greptimedb/test/logs".to_string()),
log_dir: Some("./greptimedb_data/test/logs".to_string()),
log_level: Some("debug".to_string()),
#[cfg(feature = "tokio-console")]
@@ -406,7 +409,7 @@ mod tests {
.component;
let logging_opt = options.logging;
assert_eq!("/tmp/greptimedb/test/logs", logging_opt.dir);
assert_eq!("./greptimedb_data/test/logs", logging_opt.dir);
assert_eq!("debug", logging_opt.level.as_ref().unwrap());
}
@@ -424,7 +427,7 @@ mod tests {
[logging]
level = "debug"
dir = "/tmp/greptimedb/test/logs"
dir = "./greptimedb_data/test/logs"
"#;
write!(file, "{}", toml_str).unwrap();

View File

@@ -852,7 +852,7 @@ mod tests {
[wal]
provider = "raft_engine"
dir = "/tmp/greptimedb/test/wal"
dir = "./greptimedb_data/test/wal"
file_size = "1GB"
purge_threshold = "50GB"
purge_interval = "10m"
@@ -860,7 +860,7 @@ mod tests {
sync_write = false
[storage]
data_home = "/tmp/greptimedb/"
data_home = "./greptimedb_data/"
type = "File"
[[storage.providers]]
@@ -892,7 +892,7 @@ mod tests {
[logging]
level = "debug"
dir = "/tmp/greptimedb/test/logs"
dir = "./greptimedb_data/test/logs"
"#;
write!(file, "{}", toml_str).unwrap();
let cmd = StartCommand {
@@ -922,7 +922,10 @@ mod tests {
let DatanodeWalConfig::RaftEngine(raft_engine_config) = dn_opts.wal else {
unreachable!()
};
assert_eq!("/tmp/greptimedb/test/wal", raft_engine_config.dir.unwrap());
assert_eq!(
"./greptimedb_data/test/wal",
raft_engine_config.dir.unwrap()
);
assert!(matches!(
&dn_opts.storage.store,
@@ -946,7 +949,7 @@ mod tests {
}
assert_eq!("debug", logging_opts.level.as_ref().unwrap());
assert_eq!("/tmp/greptimedb/test/logs".to_string(), logging_opts.dir);
assert_eq!("./greptimedb_data/test/logs".to_string(), logging_opts.dir);
}
#[test]
@@ -958,7 +961,7 @@ mod tests {
let opts = cmd
.load_options(&GlobalOptions {
log_dir: Some("/tmp/greptimedb/test/logs".to_string()),
log_dir: Some("./greptimedb_data/test/logs".to_string()),
log_level: Some("debug".to_string()),
#[cfg(feature = "tokio-console")]
@@ -967,7 +970,7 @@ mod tests {
.unwrap()
.component;
assert_eq!("/tmp/greptimedb/test/logs", opts.logging.dir);
assert_eq!("./greptimedb_data/test/logs", opts.logging.dir);
assert_eq!("debug", opts.logging.level.unwrap());
}

View File

@@ -56,13 +56,13 @@ fn test_load_datanode_example_config() {
metadata_cache_tti: Duration::from_secs(300),
}),
wal: DatanodeWalConfig::RaftEngine(RaftEngineConfig {
dir: Some("/tmp/greptimedb/wal".to_string()),
dir: Some("./greptimedb_data/wal".to_string()),
sync_period: Some(Duration::from_secs(10)),
recovery_parallelism: 2,
..Default::default()
}),
storage: StorageConfig {
data_home: "/tmp/greptimedb/".to_string(),
data_home: "./greptimedb_data/".to_string(),
..Default::default()
},
region_engine: vec![
@@ -159,10 +159,10 @@ fn test_load_metasrv_example_config() {
let expected = GreptimeOptions::<MetasrvOptions> {
component: MetasrvOptions {
selector: SelectorType::default(),
data_home: "/tmp/metasrv/".to_string(),
data_home: "./greptimedb_data/metasrv/".to_string(),
server_addr: "127.0.0.1:3002".to_string(),
logging: LoggingOptions {
dir: "/tmp/greptimedb/logs".to_string(),
dir: "./greptimedb_data/logs".to_string(),
level: Some("info".to_string()),
otlp_endpoint: Some(DEFAULT_OTLP_ENDPOINT.to_string()),
tracing_sample_ratio: Some(Default::default()),
@@ -202,7 +202,7 @@ fn test_load_standalone_example_config() {
component: StandaloneOptions {
default_timezone: Some("UTC".to_string()),
wal: DatanodeWalConfig::RaftEngine(RaftEngineConfig {
dir: Some("/tmp/greptimedb/wal".to_string()),
dir: Some("./greptimedb_data/wal".to_string()),
sync_period: Some(Duration::from_secs(10)),
recovery_parallelism: 2,
..Default::default()
@@ -219,7 +219,7 @@ fn test_load_standalone_example_config() {
}),
],
storage: StorageConfig {
data_home: "/tmp/greptimedb/".to_string(),
data_home: "./greptimedb_data/".to_string(),
..Default::default()
},
logging: LoggingOptions {

View File

@@ -161,7 +161,7 @@ mod tests {
[wal]
provider = "raft_engine"
dir = "/tmp/greptimedb/wal"
dir = "./greptimedb_data/wal"
file_size = "1GB"
purge_threshold = "50GB"
purge_interval = "10m"
@@ -170,7 +170,7 @@ mod tests {
[logging]
level = "debug"
dir = "/tmp/greptimedb/test/logs"
dir = "./greptimedb_data/test/logs"
"#;
write!(file, "{}", toml_str).unwrap();
@@ -246,7 +246,7 @@ mod tests {
let DatanodeWalConfig::RaftEngine(raft_engine_config) = opts.wal else {
unreachable!()
};
assert_eq!(raft_engine_config.dir.unwrap(), "/tmp/greptimedb/wal");
assert_eq!(raft_engine_config.dir.unwrap(), "./greptimedb_data/wal");
// Should be default values.
assert_eq!(opts.node_id, None);

View File

@@ -27,6 +27,7 @@ mod vector_div;
mod vector_mul;
mod vector_norm;
mod vector_sub;
mod vector_subvector;
use std::sync::Arc;
@@ -56,6 +57,7 @@ impl VectorFunction {
registry.register(Arc::new(vector_div::VectorDivFunction));
registry.register(Arc::new(vector_norm::VectorNormFunction));
registry.register(Arc::new(vector_dim::VectorDimFunction));
registry.register(Arc::new(vector_subvector::VectorSubvectorFunction));
registry.register(Arc::new(elem_sum::ElemSumFunction));
registry.register(Arc::new(elem_product::ElemProductFunction));
}

View File

@@ -0,0 +1,240 @@
// Copyright 2023 Greptime Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::borrow::Cow;
use std::fmt::Display;
use common_query::error::{InvalidFuncArgsSnafu, Result};
use common_query::prelude::{Signature, TypeSignature};
use datafusion_expr::Volatility;
use datatypes::prelude::ConcreteDataType;
use datatypes::scalars::ScalarVectorBuilder;
use datatypes::vectors::{BinaryVectorBuilder, MutableVector, VectorRef};
use snafu::ensure;
use crate::function::{Function, FunctionContext};
use crate::scalars::vector::impl_conv::{as_veclit, as_veclit_if_const, veclit_to_binlit};
const NAME: &str = "vec_subvector";
/// Returns a subvector from start(included) to end(excluded) index.
///
/// # Example
///
/// ```sql
/// SELECT vec_to_string(vec_subvector("[1, 2, 3, 4, 5]", 1, 3)) as result;
///
/// +---------+
/// | result |
/// +---------+
/// | [2, 3] |
/// +---------+
///
/// ```
///
#[derive(Debug, Clone, Default)]
pub struct VectorSubvectorFunction;
impl Function for VectorSubvectorFunction {
fn name(&self) -> &str {
NAME
}
fn return_type(&self, _input_types: &[ConcreteDataType]) -> Result<ConcreteDataType> {
Ok(ConcreteDataType::binary_datatype())
}
fn signature(&self) -> Signature {
Signature::one_of(
vec![
TypeSignature::Exact(vec![
ConcreteDataType::string_datatype(),
ConcreteDataType::int64_datatype(),
ConcreteDataType::int64_datatype(),
]),
TypeSignature::Exact(vec![
ConcreteDataType::binary_datatype(),
ConcreteDataType::int64_datatype(),
ConcreteDataType::int64_datatype(),
]),
],
Volatility::Immutable,
)
}
fn eval(&self, _func_ctx: &FunctionContext, columns: &[VectorRef]) -> Result<VectorRef> {
ensure!(
columns.len() == 3,
InvalidFuncArgsSnafu {
err_msg: format!(
"The length of the args is not correct, expect exactly three, have: {}",
columns.len()
)
}
);
let arg0 = &columns[0];
let arg1 = &columns[1];
let arg2 = &columns[2];
ensure!(
arg0.len() == arg1.len() && arg1.len() == arg2.len(),
InvalidFuncArgsSnafu {
err_msg: format!(
"The lengths of the vector are not aligned, args 0: {}, args 1: {}, args 2: {}",
arg0.len(),
arg1.len(),
arg2.len()
)
}
);
let len = arg0.len();
let mut result = BinaryVectorBuilder::with_capacity(len);
if len == 0 {
return Ok(result.to_vector());
}
let arg0_const = as_veclit_if_const(arg0)?;
for i in 0..len {
let arg0 = match arg0_const.as_ref() {
Some(arg0) => Some(Cow::Borrowed(arg0.as_ref())),
None => as_veclit(arg0.get_ref(i))?,
};
let arg1 = arg1.get(i).as_i64();
let arg2 = arg2.get(i).as_i64();
let (Some(arg0), Some(arg1), Some(arg2)) = (arg0, arg1, arg2) else {
result.push_null();
continue;
};
ensure!(
0 <= arg1 && arg1 <= arg2 && arg2 as usize <= arg0.len(),
InvalidFuncArgsSnafu {
err_msg: format!(
"Invalid start and end indices: start={}, end={}, vec_len={}",
arg1,
arg2,
arg0.len()
)
}
);
let subvector = &arg0[arg1 as usize..arg2 as usize];
let binlit = veclit_to_binlit(subvector);
result.push(Some(&binlit));
}
Ok(result.to_vector())
}
}
impl Display for VectorSubvectorFunction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", NAME.to_ascii_uppercase())
}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use common_query::error::Error;
use datatypes::vectors::{Int64Vector, StringVector};
use super::*;
use crate::function::FunctionContext;
#[test]
fn test_subvector() {
let func = VectorSubvectorFunction;
let input0 = Arc::new(StringVector::from(vec![
Some("[1.0, 2.0, 3.0, 4.0, 5.0]".to_string()),
Some("[6.0, 7.0, 8.0, 9.0, 10.0]".to_string()),
None,
Some("[11.0, 12.0, 13.0]".to_string()),
]));
let input1 = Arc::new(Int64Vector::from(vec![Some(1), Some(0), Some(0), Some(1)]));
let input2 = Arc::new(Int64Vector::from(vec![Some(3), Some(5), Some(2), Some(3)]));
let result = func
.eval(&FunctionContext::default(), &[input0, input1, input2])
.unwrap();
let result = result.as_ref();
assert_eq!(result.len(), 4);
assert_eq!(
result.get_ref(0).as_binary().unwrap(),
Some(veclit_to_binlit(&[2.0, 3.0]).as_slice())
);
assert_eq!(
result.get_ref(1).as_binary().unwrap(),
Some(veclit_to_binlit(&[6.0, 7.0, 8.0, 9.0, 10.0]).as_slice())
);
assert!(result.get_ref(2).is_null());
assert_eq!(
result.get_ref(3).as_binary().unwrap(),
Some(veclit_to_binlit(&[12.0, 13.0]).as_slice())
);
}
#[test]
fn test_subvector_error() {
let func = VectorSubvectorFunction;
let input0 = Arc::new(StringVector::from(vec![
Some("[1.0, 2.0, 3.0]".to_string()),
Some("[4.0, 5.0, 6.0]".to_string()),
]));
let input1 = Arc::new(Int64Vector::from(vec![Some(1), Some(2)]));
let input2 = Arc::new(Int64Vector::from(vec![Some(3)]));
let result = func.eval(&FunctionContext::default(), &[input0, input1, input2]);
match result {
Err(Error::InvalidFuncArgs { err_msg, .. }) => {
assert_eq!(
err_msg,
"The lengths of the vector are not aligned, args 0: 2, args 1: 2, args 2: 1"
)
}
_ => unreachable!(),
}
}
#[test]
fn test_subvector_invalid_indices() {
let func = VectorSubvectorFunction;
let input0 = Arc::new(StringVector::from(vec![
Some("[1.0, 2.0, 3.0]".to_string()),
Some("[4.0, 5.0, 6.0]".to_string()),
]));
let input1 = Arc::new(Int64Vector::from(vec![Some(1), Some(3)]));
let input2 = Arc::new(Int64Vector::from(vec![Some(3), Some(4)]));
let result = func.eval(&FunctionContext::default(), &[input0, input1, input2]);
match result {
Err(Error::InvalidFuncArgs { err_msg, .. }) => {
assert_eq!(
err_msg,
"Invalid start and end indices: start=3, end=4, vec_len=3"
)
}
_ => unreachable!(),
}
}
}

View File

@@ -111,7 +111,7 @@ impl Eq for LoggingOptions {}
impl Default for LoggingOptions {
fn default() -> Self {
Self {
dir: "/tmp/greptimedb/logs".to_string(),
dir: "./greptimedb_data/logs".to_string(),
level: None,
log_format: LogFormat::Text,
enable_otlp_tracing: false,

View File

@@ -36,7 +36,7 @@ use servers::Mode;
pub const DEFAULT_OBJECT_STORE_CACHE_SIZE: ReadableSize = ReadableSize::gb(5);
/// Default data home in file storage
const DEFAULT_DATA_HOME: &str = "/tmp/greptimedb";
const DEFAULT_DATA_HOME: &str = "./greptimedb_data";
/// Object storage config
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]

View File

@@ -285,6 +285,20 @@ impl Value {
}
}
/// Cast Value to i64. Return None if value is not a valid int64 data type.
pub fn as_i64(&self) -> Option<i64> {
match self {
Value::Int8(v) => Some(*v as _),
Value::Int16(v) => Some(*v as _),
Value::Int32(v) => Some(*v as _),
Value::Int64(v) => Some(*v),
Value::UInt8(v) => Some(*v as _),
Value::UInt16(v) => Some(*v as _),
Value::UInt32(v) => Some(*v as _),
_ => None,
}
}
/// Cast Value to u64. Return None if value is not a valid uint64 data type.
pub fn as_u64(&self) -> Option<u64> {
match self {
@@ -295,7 +309,6 @@ impl Value {
_ => None,
}
}
/// Cast Value to f64. Return None if it's not castable;
pub fn as_f64_lossy(&self) -> Option<f64> {
match self {

View File

@@ -70,7 +70,7 @@ use crate::state::{become_follower, become_leader, StateRef};
pub const TABLE_ID_SEQ: &str = "table_id";
pub const FLOW_ID_SEQ: &str = "flow_id";
pub const METASRV_HOME: &str = "/tmp/metasrv";
pub const METASRV_HOME: &str = "./greptimedb_data/metasrv";
#[cfg(feature = "pg_kvbackend")]
pub const DEFAULT_META_TABLE_NAME: &str = "greptime_metakv";

View File

@@ -53,6 +53,8 @@ pub(crate) struct FileCache {
///
/// File id is enough to identity a file uniquely.
memory_index: Cache<IndexKey, IndexValue>,
/// Capacity of the cache.
capacity: ReadableSize,
}
pub(crate) type FileCacheRef = Arc<FileCache>;
@@ -103,6 +105,7 @@ impl FileCache {
FileCache {
local_store,
memory_index,
capacity,
}
}
@@ -198,6 +201,20 @@ impl FileCache {
}
}
/// Returns the available space in the file cache.
pub(crate) fn available_space(&self) -> u64 {
if self.capacity.as_bytes() > self.memory_index.weighted_size() {
self.capacity.as_bytes() - self.memory_index.weighted_size()
} else {
0
}
}
/// Returns the capacity of the file cache.
pub(crate) fn capacity(&self) -> u64 {
self.capacity.as_bytes()
}
async fn recover_inner(&self) -> Result<()> {
let now = Instant::now();
let mut lister = self

View File

@@ -263,6 +263,16 @@ impl WriteCache {
Ok(())
}
/// Returns the available space in the write cache.
pub(crate) fn available_space(&self) -> u64 {
self.file_cache.available_space()
}
/// Returns the capacity of the write cache.
pub(crate) fn capacity(&self) -> u64 {
self.file_cache.capacity()
}
/// Uploads a Parquet file or a Puffin file to the remote object store.
async fn upload(
&self,

View File

@@ -15,6 +15,7 @@
//! Handling open request.
use std::sync::Arc;
use std::time::Instant;
use common_telemetry::info;
use object_store::util::join_path;
@@ -24,14 +25,18 @@ use store_api::region_request::RegionOpenRequest;
use store_api::storage::RegionId;
use table::requests::STORAGE_KEY;
use crate::cache::file_cache::{FileType, IndexKey};
use crate::cache::write_cache::WriteCacheRef;
use crate::error::{
ObjectStoreNotFoundSnafu, OpenDalSnafu, OpenRegionSnafu, RegionNotFoundSnafu, Result,
};
use crate::metrics::WRITE_CACHE_INFLIGHT_DOWNLOAD;
use crate::region::opener::RegionOpener;
use crate::request::OptionOutputTx;
use crate::sst::location;
use crate::wal::entry_distributor::WalEntryReceiver;
use crate::worker::handle_drop::remove_region_dir_once;
use crate::worker::{RegionWorkerLoop, DROPPING_MARKER_FILE};
use crate::worker::{MitoRegionRef, RegionWorkerLoop, DROPPING_MARKER_FILE};
impl<S: LogStore> RegionWorkerLoop<S> {
async fn check_and_cleanup_region(
@@ -118,6 +123,7 @@ impl<S: LogStore> RegionWorkerLoop<S> {
let opening_regions = self.opening_regions.clone();
let region_count = self.region_count.clone();
let worker_id = self.id;
let write_cache = self.cache_manager.write_cache().cloned();
opening_regions.insert_sender(region_id, sender);
common_runtime::spawn_global(async move {
match opener.open(&config, &wal).await {
@@ -126,12 +132,17 @@ impl<S: LogStore> RegionWorkerLoop<S> {
region_count.inc();
// Insert the Region into the RegionMap.
regions.insert_region(Arc::new(region));
let region = Arc::new(region);
regions.insert_region(region.clone());
let senders = opening_regions.remove_sender(region_id);
for sender in senders {
sender.send(Ok(0));
}
if let Some(write_cache) = write_cache {
prefetch_latest_ssts(region, write_cache).await;
}
}
Err(err) => {
let senders = opening_regions.remove_sender(region_id);
@@ -144,3 +155,85 @@ impl<S: LogStore> RegionWorkerLoop<S> {
});
}
}
/// Download latest SSTs from the remote storage for the region.
async fn prefetch_latest_ssts(region: MitoRegionRef, write_cache: WriteCacheRef) {
let version = region.version();
// Sort ssts by time range in descending order.
let mut ssts: Vec<_> = version
.ssts
.levels()
.iter()
.flat_map(|level| level.files())
.collect();
ssts.sort_unstable_by(|left, right| right.time_range().1.cmp(&left.time_range().1));
let layer = region.access_layer.clone();
let region_id = region.region_id;
// Prefetch the latest SSTs.
let mut has_err = false;
let mut fetched = 0;
let mut downloaded_bytes = 0;
let start = Instant::now();
for sst in ssts {
if has_err || write_cache.available_space() <= write_cache.capacity() / 2 {
break;
}
WRITE_CACHE_INFLIGHT_DOWNLOAD.add(1);
let file_meta = sst.meta_ref();
let index_key = IndexKey::new(region_id, file_meta.file_id, FileType::Parquet);
let remote_path = location::sst_file_path(layer.region_dir(), file_meta.file_id);
let file_size = file_meta.file_size;
if let Err(err) = write_cache
.download(index_key, &remote_path, layer.object_store(), file_size)
.await
{
common_telemetry::error!(
err; "Failed to download parquet file, region_id: {}, index_key: {:?}, remote_path: {}", region_id, index_key, remote_path
);
has_err = true;
} else {
fetched += 1;
downloaded_bytes += file_size;
}
let is_index_exist = file_meta.exists_index();
if !has_err && is_index_exist {
let index_file_size = file_meta.index_file_size();
let index_file_index_key =
IndexKey::new(region_id, file_meta.file_id, FileType::Puffin);
let index_remote_path =
location::index_file_path(layer.region_dir(), file_meta.file_id);
// also download puffin file
if let Err(err) = write_cache
.download(
index_file_index_key,
&index_remote_path,
layer.object_store(),
index_file_size,
)
.await
{
common_telemetry::error!(
err; "Failed to download puffin file, region_id: {}, index_file_index_key: {:?}, index_remote_path: {}", region_id, index_file_index_key, index_remote_path
);
has_err = true;
} else {
fetched += 1;
downloaded_bytes += index_file_size;
}
}
WRITE_CACHE_INFLIGHT_DOWNLOAD.sub(1);
}
common_telemetry::info!(
"region {} prefetched {} files with total {} bytes, elapsed: {:?}",
region_id,
fetched,
downloaded_bytes,
start.elapsed(),
);
}

View File

@@ -12,12 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::io::BufRead;
use std::str::FromStr;
use std::sync::Arc;
use std::time::Instant;
use api::v1::RowInsertRequests;
use async_trait::async_trait;
use axum::body::Bytes;
use axum::extract::{FromRequest, Multipart, Path, Query, Request, State};
use axum::http::header::CONTENT_TYPE;
use axum::http::{HeaderMap, StatusCode};
@@ -389,8 +391,8 @@ pub struct PipelineDryrunParams {
/// Check if the payload is valid json
/// Check if the payload contains pipeline or pipeline_name and data
/// Return Some if valid, None if invalid
fn check_pipeline_dryrun_params_valid(payload: &str) -> Option<PipelineDryrunParams> {
match serde_json::from_str::<PipelineDryrunParams>(payload) {
fn check_pipeline_dryrun_params_valid(payload: &Bytes) -> Option<PipelineDryrunParams> {
match serde_json::from_slice::<PipelineDryrunParams>(payload) {
// payload with pipeline or pipeline_name and data is array
Ok(params) if params.pipeline.is_some() || params.pipeline_name.is_some() => Some(params),
// because of the pipeline_name or pipeline is required
@@ -432,7 +434,7 @@ pub async fn pipeline_dryrun(
Query(query_params): Query<LogIngesterQueryParams>,
Extension(mut query_ctx): Extension<QueryContext>,
TypedHeader(content_type): TypedHeader<ContentType>,
payload: String,
payload: Bytes,
) -> Result<Response> {
let handler = log_state.log_handler;
@@ -514,7 +516,7 @@ pub async fn log_ingester(
Extension(mut query_ctx): Extension<QueryContext>,
TypedHeader(content_type): TypedHeader<ContentType>,
headers: HeaderMap,
payload: String,
payload: Bytes,
) -> Result<HttpResponse> {
// validate source and payload
let source = query_params.source.as_deref();
@@ -565,40 +567,45 @@ pub async fn log_ingester(
fn extract_pipeline_value_by_content_type(
content_type: ContentType,
payload: String,
payload: Bytes,
ignore_errors: bool,
) -> Result<Vec<Value>> {
Ok(match content_type {
ct if ct == *JSON_CONTENT_TYPE => transform_ndjson_array_factory(
Deserializer::from_str(&payload).into_iter(),
Deserializer::from_slice(&payload).into_iter(),
ignore_errors,
)?,
ct if ct == *NDJSON_CONTENT_TYPE => {
let mut result = Vec::with_capacity(1000);
for (index, line) in payload.lines().enumerate() {
match serde_json::from_str(line) {
Ok(v) => {
result.push(v);
}
Err(_) => {
if !ignore_errors {
warn!(
"invalid json item in array, index: {:?}, value: {:?}",
index, line
);
return InvalidParameterSnafu {
reason: format!("invalid item:{} in array", line),
}
.fail();
let line = match line {
Ok(line) if !line.is_empty() => line,
Ok(_) => continue, // Skip empty lines
Err(_) if ignore_errors => continue,
Err(e) => {
warn!(e; "invalid string at index: {}", index);
return InvalidParameterSnafu {
reason: format!("invalid line at index: {}", index),
}
.fail();
}
};
if let Ok(v) = serde_json::from_str(&line) {
result.push(v);
} else if !ignore_errors {
warn!("invalid JSON at index: {}, content: {:?}", index, line);
return InvalidParameterSnafu {
reason: format!("invalid JSON at index: {}", index),
}
.fail();
}
}
result
}
ct if ct == *TEXT_CONTENT_TYPE || ct == *TEXT_UTF8_CONTENT_TYPE => payload
.lines()
.filter(|line| !line.is_empty())
.filter_map(|line| line.ok().filter(|line| !line.is_empty()))
.map(|line| json!({"message": line}))
.collect(),
_ => UnsupportedContentTypeSnafu { content_type }.fail()?,
@@ -677,7 +684,8 @@ pub(crate) async fn ingest_logs_inner(
pub trait LogValidator: Send + Sync {
/// validate payload by source before processing
/// Return a `Some` result to indicate validation failure.
async fn validate(&self, source: Option<&str>, payload: &str) -> Option<Result<HttpResponse>>;
async fn validate(&self, source: Option<&str>, payload: &Bytes)
-> Option<Result<HttpResponse>>;
}
pub type LogValidatorRef = Arc<dyn LogValidator + 'static>;
@@ -731,17 +739,17 @@ mod tests {
{"a": 1}
{"b": 2"}
{"c": 1}
"#;
"#
.as_bytes();
let payload = Bytes::from_static(payload);
let fail_rest =
extract_pipeline_value_by_content_type(ContentType::json(), payload.to_string(), true);
extract_pipeline_value_by_content_type(ContentType::json(), payload.clone(), true);
assert!(fail_rest.is_ok());
assert_eq!(fail_rest.unwrap(), vec![json!({"a": 1})]);
let fail_only_wrong = extract_pipeline_value_by_content_type(
NDJSON_CONTENT_TYPE.clone(),
payload.to_string(),
true,
);
let fail_only_wrong =
extract_pipeline_value_by_content_type(NDJSON_CONTENT_TYPE.clone(), payload, true);
assert!(fail_only_wrong.is_ok());
assert_eq!(
fail_only_wrong.unwrap(),

View File

@@ -391,7 +391,7 @@ async fn test_config() {
[logging]
level = "debug"
dir = "/tmp/greptimedb/test/logs"
dir = "./greptimedb_data/test/logs"
"#;
let rs = http_handler::config(State(GreptimeOptionsConfigState {
greptime_config_options: toml_str.to_string(),

View File

@@ -326,3 +326,53 @@ FROM (
| [7.0, 8.0, 9.0, 10.0] | 4 |
+-----------------------+------------+
SELECT vec_to_string(vec_subvector('[1.0,2.0,3.0,4.0,5.0]', 0, 3));
+-------------------------------------------------------------------------------+
| vec_to_string(vec_subvector(Utf8("[1.0,2.0,3.0,4.0,5.0]"),Int64(0),Int64(3))) |
+-------------------------------------------------------------------------------+
| [1,2,3] |
+-------------------------------------------------------------------------------+
SELECT vec_to_string(vec_subvector('[1.0,2.0,3.0,4.0,5.0]', 5, 5));
+-------------------------------------------------------------------------------+
| vec_to_string(vec_subvector(Utf8("[1.0,2.0,3.0,4.0,5.0]"),Int64(5),Int64(5))) |
+-------------------------------------------------------------------------------+
| [] |
+-------------------------------------------------------------------------------+
SELECT v, vec_to_string(vec_subvector(v, 3, 5))
FROM (
SELECT '[1.0, 2.0, 3.0, 4.0, 5.0]' AS v
UNION ALL
SELECT '[-1.0, -2.0, -3.0, -4.0, -5.0, -6.0]' AS v
UNION ALL
SELECT '[4.0, 5.0, 6.0, 10, -8, 100]' AS v
) ORDER BY v;
+--------------------------------------+---------------------------------------------------+
| v | vec_to_string(vec_subvector(v,Int64(3),Int64(5))) |
+--------------------------------------+---------------------------------------------------+
| [-1.0, -2.0, -3.0, -4.0, -5.0, -6.0] | [-4,-5] |
| [1.0, 2.0, 3.0, 4.0, 5.0] | [4,5] |
| [4.0, 5.0, 6.0, 10, -8, 100] | [10,-8] |
+--------------------------------------+---------------------------------------------------+
SELECT vec_to_string(vec_subvector(v, 0, 5))
FROM (
SELECT '[1.1, 2.2, 3.3, 4.4, 5.5]' AS v
UNION ALL
SELECT '[-1.1, -2.1, -3.1, -4.1, -5.1, -6.1]' AS v
UNION ALL
SELECT '[4.0, 5.0, 6.0, 10, -8, 100]' AS v
) ORDER BY v;
+---------------------------------------------------+
| vec_to_string(vec_subvector(v,Int64(0),Int64(5))) |
+---------------------------------------------------+
| [-1.1,-2.1,-3.1,-4.1,-5.1] |
| [1.1,2.2,3.3,4.4,5.5] |
| [4,5,6,10,-8] |
+---------------------------------------------------+

View File

@@ -99,3 +99,26 @@ FROM (
UNION ALL
SELECT '[7.0, 8.0, 9.0, 10.0]' AS v
) Order By vec_dim(v) ASC;
SELECT vec_to_string(vec_subvector('[1.0,2.0,3.0,4.0,5.0]', 0, 3));
SELECT vec_to_string(vec_subvector('[1.0,2.0,3.0,4.0,5.0]', 5, 5));
SELECT v, vec_to_string(vec_subvector(v, 3, 5))
FROM (
SELECT '[1.0, 2.0, 3.0, 4.0, 5.0]' AS v
UNION ALL
SELECT '[-1.0, -2.0, -3.0, -4.0, -5.0, -6.0]' AS v
UNION ALL
SELECT '[4.0, 5.0, 6.0, 10, -8, 100]' AS v
) ORDER BY v;
SELECT vec_to_string(vec_subvector(v, 0, 5))
FROM (
SELECT '[1.1, 2.2, 3.3, 4.4, 5.5]' AS v
UNION ALL
SELECT '[-1.1, -2.1, -3.1, -4.1, -5.1, -6.1]' AS v
UNION ALL
SELECT '[4.0, 5.0, 6.0, 10, -8, 100]' AS v
) ORDER BY v;