mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2025-12-26 08:00:01 +00:00
feat: add build() function to return the database build info (#2919)
* feat: add build function and register it build() function to return the database build info #2909 * refactor: fix typos and change code structure * test: add test for build() * refactor: cargo fmt and eliminate warnings * Apply suggestions from code review Co-authored-by: Weny Xu <wenymedia@gmail.com> * refactor: move system.sql to a new directory --------- Co-authored-by: Weny Xu <wenymedia@gmail.com>
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1664,6 +1664,7 @@ name = "common-function"
|
||||
version = "0.4.4"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"build-data",
|
||||
"chrono-tz 0.6.3",
|
||||
"common-error",
|
||||
"common-macro",
|
||||
|
||||
@@ -6,6 +6,7 @@ license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
arc-swap = "1.0"
|
||||
build-data = "0.1"
|
||||
chrono-tz = "0.6"
|
||||
common-error.workspace = true
|
||||
common-macro.workspace = true
|
||||
|
||||
@@ -18,12 +18,13 @@ use std::sync::{Arc, RwLock};
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use crate::function::FunctionRef;
|
||||
use crate::scalars::aggregate::{AggregateFunctionMetaRef, AggregateFunctions};
|
||||
use crate::scalars::date::DateFunction;
|
||||
use crate::scalars::function::FunctionRef;
|
||||
use crate::scalars::math::MathFunction;
|
||||
use crate::scalars::numpy::NumpyFunction;
|
||||
use crate::scalars::timestamp::TimestampFunction;
|
||||
use crate::system::SystemFunction;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct FunctionRegistry {
|
||||
@@ -79,7 +80,7 @@ pub static FUNCTION_REGISTRY: Lazy<Arc<FunctionRegistry>> = Lazy::new(|| {
|
||||
DateFunction::register(&function_registry);
|
||||
|
||||
AggregateFunctions::register(&function_registry);
|
||||
|
||||
SystemFunction::register(&function_registry);
|
||||
Arc::new(function_registry)
|
||||
});
|
||||
|
||||
@@ -13,5 +13,8 @@
|
||||
// limitations under the License.
|
||||
|
||||
pub mod scalars;
|
||||
pub mod system;
|
||||
|
||||
pub mod function;
|
||||
pub mod function_registry;
|
||||
pub mod helper;
|
||||
|
||||
@@ -13,16 +13,11 @@
|
||||
// limitations under the License.
|
||||
|
||||
pub mod aggregate;
|
||||
mod date;
|
||||
pub(crate) mod date;
|
||||
pub mod expression;
|
||||
pub mod function;
|
||||
pub mod function_registry;
|
||||
pub mod math;
|
||||
pub mod numpy;
|
||||
#[cfg(test)]
|
||||
pub(crate) mod test;
|
||||
mod timestamp;
|
||||
pub(crate) mod timestamp;
|
||||
pub mod udf;
|
||||
|
||||
pub use function::{Function, FunctionRef};
|
||||
pub use function_registry::{FunctionRegistry, FUNCTION_REGISTRY};
|
||||
|
||||
@@ -33,7 +33,7 @@ pub use polyval::PolyvalAccumulatorCreator;
|
||||
pub use scipy_stats_norm_cdf::ScipyStatsNormCdfAccumulatorCreator;
|
||||
pub use scipy_stats_norm_pdf::ScipyStatsNormPdfAccumulatorCreator;
|
||||
|
||||
use crate::scalars::FunctionRegistry;
|
||||
use crate::function_registry::FunctionRegistry;
|
||||
|
||||
/// A function creates `AggregateFunctionCreator`.
|
||||
/// "Aggregator" *is* AggregatorFunction. Since the later one is long, we named an short alias for it.
|
||||
|
||||
@@ -19,7 +19,7 @@ mod date_sub;
|
||||
use date_add::DateAddFunction;
|
||||
use date_sub::DateSubFunction;
|
||||
|
||||
use crate::scalars::function_registry::FunctionRegistry;
|
||||
use crate::function_registry::FunctionRegistry;
|
||||
|
||||
pub(crate) struct DateFunction;
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ use datatypes::value::ValueRef;
|
||||
use datatypes::vectors::VectorRef;
|
||||
use snafu::ensure;
|
||||
|
||||
use crate::function::{Function, FunctionContext};
|
||||
use crate::helper;
|
||||
use crate::scalars::function::{Function, FunctionContext};
|
||||
|
||||
/// A function adds an interval value to Timestamp, Date or DateTime, and return the result.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
@@ -149,7 +149,6 @@ mod tests {
|
||||
};
|
||||
|
||||
use super::{DateAddFunction, *};
|
||||
use crate::scalars::Function;
|
||||
|
||||
#[test]
|
||||
fn test_date_add_misc() {
|
||||
|
||||
@@ -22,8 +22,8 @@ use datatypes::value::ValueRef;
|
||||
use datatypes::vectors::VectorRef;
|
||||
use snafu::ensure;
|
||||
|
||||
use crate::function::{Function, FunctionContext};
|
||||
use crate::helper;
|
||||
use crate::scalars::function::{Function, FunctionContext};
|
||||
|
||||
/// A function subtracts an interval value to Timestamp, Date or DateTime, and return the result.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
@@ -150,7 +150,6 @@ mod tests {
|
||||
};
|
||||
|
||||
use super::{DateSubFunction, *};
|
||||
use crate::scalars::Function;
|
||||
|
||||
#[test]
|
||||
fn test_date_sub_misc() {
|
||||
|
||||
@@ -28,9 +28,8 @@ pub use pow::PowFunction;
|
||||
pub use rate::RateFunction;
|
||||
use snafu::ResultExt;
|
||||
|
||||
use super::function::FunctionContext;
|
||||
use super::Function;
|
||||
use crate::scalars::function_registry::FunctionRegistry;
|
||||
use crate::function::{Function, FunctionContext};
|
||||
use crate::function_registry::FunctionRegistry;
|
||||
|
||||
pub(crate) struct MathFunction;
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ use datatypes::with_match_primitive_type_id;
|
||||
use num::traits::Pow;
|
||||
use num_traits::AsPrimitive;
|
||||
|
||||
use crate::function::{Function, FunctionContext};
|
||||
use crate::scalars::expression::{scalar_binary_op, EvalContext};
|
||||
use crate::scalars::function::{Function, FunctionContext};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct PowFunction;
|
||||
@@ -83,6 +83,7 @@ mod tests {
|
||||
use datatypes::vectors::{Float32Vector, Int8Vector};
|
||||
|
||||
use super::*;
|
||||
use crate::function::FunctionContext;
|
||||
#[test]
|
||||
fn test_pow_function() {
|
||||
let pow = PowFunction;
|
||||
|
||||
@@ -23,7 +23,7 @@ use datatypes::prelude::*;
|
||||
use datatypes::vectors::{Helper, VectorRef};
|
||||
use snafu::ResultExt;
|
||||
|
||||
use crate::scalars::function::{Function, FunctionContext};
|
||||
use crate::function::{Function, FunctionContext};
|
||||
|
||||
/// generates rates from a sequence of adjacent data points.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
|
||||
@@ -19,7 +19,7 @@ use std::sync::Arc;
|
||||
|
||||
use clip::ClipFunction;
|
||||
|
||||
use crate::scalars::function_registry::FunctionRegistry;
|
||||
use crate::function_registry::FunctionRegistry;
|
||||
|
||||
pub(crate) struct NumpyFunction;
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ use datatypes::prelude::*;
|
||||
use datatypes::vectors::PrimitiveVector;
|
||||
use paste::paste;
|
||||
|
||||
use crate::function::{Function, FunctionContext};
|
||||
use crate::scalars::expression::{scalar_binary_op, EvalContext};
|
||||
use crate::scalars::function::{Function, FunctionContext};
|
||||
|
||||
/// numpy.clip function, <https://numpy.org/doc/stable/reference/generated/numpy.clip.html>
|
||||
#[derive(Clone, Debug, Default)]
|
||||
|
||||
@@ -20,8 +20,8 @@ use common_query::prelude::{Signature, Volatility};
|
||||
use datatypes::data_type::ConcreteDataType;
|
||||
use datatypes::prelude::VectorRef;
|
||||
|
||||
use crate::function::{Function, FunctionContext};
|
||||
use crate::scalars::expression::{scalar_binary_op, EvalContext};
|
||||
use crate::scalars::function::{Function, FunctionContext};
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub(crate) struct TestAndFunction;
|
||||
|
||||
@@ -19,7 +19,7 @@ mod to_unixtime;
|
||||
use greatest::GreatestFunction;
|
||||
use to_unixtime::ToUnixtimeFunction;
|
||||
|
||||
use crate::scalars::function_registry::FunctionRegistry;
|
||||
use crate::function_registry::FunctionRegistry;
|
||||
|
||||
pub(crate) struct TimestampFunction;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ use datatypes::prelude::ConcreteDataType;
|
||||
use datatypes::vectors::{Helper, VectorRef};
|
||||
use snafu::{ensure, ResultExt};
|
||||
|
||||
use crate::scalars::function::{Function, FunctionContext};
|
||||
use crate::function::{Function, FunctionContext};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct GreatestFunction;
|
||||
@@ -113,10 +113,7 @@ mod tests {
|
||||
use datatypes::value::Value;
|
||||
use datatypes::vectors::{DateVector, StringVector, Vector};
|
||||
|
||||
use super::GreatestFunction;
|
||||
use crate::scalars::function::FunctionContext;
|
||||
use crate::scalars::Function;
|
||||
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_greatest_takes_string_vector() {
|
||||
let function = GreatestFunction;
|
||||
|
||||
@@ -23,7 +23,7 @@ use datatypes::prelude::ConcreteDataType;
|
||||
use datatypes::vectors::{Int64Vector, VectorRef};
|
||||
use snafu::ensure;
|
||||
|
||||
use crate::scalars::function::{Function, FunctionContext};
|
||||
use crate::function::{Function, FunctionContext};
|
||||
|
||||
/// A function to convert the column into the unix timestamp in seconds.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
@@ -152,7 +152,6 @@ mod tests {
|
||||
};
|
||||
|
||||
use super::{ToUnixtimeFunction, *};
|
||||
use crate::scalars::Function;
|
||||
|
||||
#[test]
|
||||
fn test_string_to_unixtime() {
|
||||
|
||||
@@ -23,7 +23,7 @@ use datatypes::prelude::*;
|
||||
use datatypes::vectors::Helper;
|
||||
use snafu::ResultExt;
|
||||
|
||||
use crate::scalars::function::{FunctionContext, FunctionRef};
|
||||
use crate::function::{FunctionContext, FunctionRef};
|
||||
|
||||
/// Create a ScalarUdf from function.
|
||||
pub fn create_udf(func: FunctionRef) -> ScalarUdf {
|
||||
@@ -72,7 +72,7 @@ mod tests {
|
||||
use datatypes::vectors::{BooleanVector, ConstantVector};
|
||||
|
||||
use super::*;
|
||||
use crate::scalars::function::Function;
|
||||
use crate::function::Function;
|
||||
use crate::scalars::test::TestAndFunction;
|
||||
|
||||
#[test]
|
||||
|
||||
29
src/common/function/src/system.rs
Normal file
29
src/common/function/src/system.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
// 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.
|
||||
|
||||
pub mod build;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use build::BuildFunction;
|
||||
|
||||
use crate::function_registry::FunctionRegistry;
|
||||
|
||||
pub(crate) struct SystemFunction;
|
||||
|
||||
impl SystemFunction {
|
||||
pub fn register(registry: &FunctionRegistry) {
|
||||
registry.register(Arc::new(BuildFunction));
|
||||
}
|
||||
}
|
||||
102
src/common/function/src/system/build.rs
Normal file
102
src/common/function/src/system/build.rs
Normal file
@@ -0,0 +1,102 @@
|
||||
// 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::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use common_query::error::Result;
|
||||
use common_query::prelude::{Signature, Volatility};
|
||||
use datatypes::prelude::*;
|
||||
use datatypes::vectors::{StringVector, VectorRef};
|
||||
|
||||
use crate::function::{Function, FunctionContext};
|
||||
|
||||
const DEFAULT_VALUE: &str = "unknown";
|
||||
|
||||
/// Generates build information
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct BuildFunction;
|
||||
|
||||
impl fmt::Display for BuildFunction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "BUILD")
|
||||
}
|
||||
}
|
||||
|
||||
impl Function for BuildFunction {
|
||||
fn name(&self) -> &str {
|
||||
"build"
|
||||
}
|
||||
|
||||
fn return_type(&self, _input_types: &[ConcreteDataType]) -> Result<ConcreteDataType> {
|
||||
Ok(ConcreteDataType::string_datatype())
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::uniform(
|
||||
0,
|
||||
vec![ConcreteDataType::string_datatype()],
|
||||
Volatility::Immutable,
|
||||
)
|
||||
}
|
||||
|
||||
fn eval(&self, _func_ctx: FunctionContext, _columns: &[VectorRef]) -> Result<VectorRef> {
|
||||
let build_info = format!(
|
||||
"branch: {}\ncommit: {}\ncommit short: {}\ndirty: {}\nversion: {}",
|
||||
build_data::get_git_branch().unwrap_or_else(|_| DEFAULT_VALUE.to_string()),
|
||||
build_data::get_git_commit().unwrap_or_else(|_| DEFAULT_VALUE.to_string()),
|
||||
build_data::get_git_commit_short().unwrap_or_else(|_| DEFAULT_VALUE.to_string()),
|
||||
build_data::get_git_dirty().map_or(DEFAULT_VALUE.to_string(), |v| v.to_string()),
|
||||
env!("CARGO_PKG_VERSION")
|
||||
);
|
||||
|
||||
let v = Arc::new(StringVector::from(vec![build_info]));
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::Arc;
|
||||
|
||||
use common_query::prelude::TypeSignature;
|
||||
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_build_function() {
|
||||
let build = BuildFunction;
|
||||
assert_eq!("build", build.name());
|
||||
assert_eq!(
|
||||
ConcreteDataType::string_datatype(),
|
||||
build.return_type(&[]).unwrap()
|
||||
);
|
||||
assert!(matches!(build.signature(),
|
||||
Signature {
|
||||
type_signature: TypeSignature::Uniform(0, valid_types),
|
||||
volatility: Volatility::Immutable
|
||||
} if valid_types == vec![ConcreteDataType::string_datatype()]
|
||||
));
|
||||
let build_info = format!(
|
||||
"branch: {}\ncommit: {}\ncommit short: {}\ndirty: {}\nversion: {}",
|
||||
build_data::get_git_branch().unwrap_or_else(|_| DEFAULT_VALUE.to_string()),
|
||||
build_data::get_git_commit().unwrap_or_else(|_| DEFAULT_VALUE.to_string()),
|
||||
build_data::get_git_commit_short().unwrap_or_else(|_| DEFAULT_VALUE.to_string()),
|
||||
build_data::get_git_dirty().map_or(DEFAULT_VALUE.to_string(), |v| v.to_string()),
|
||||
env!("CARGO_PKG_VERSION")
|
||||
);
|
||||
let vector = build.eval(FunctionContext::default(), &[]).unwrap();
|
||||
let expect: VectorRef = Arc::new(StringVector::from(vec![build_info]));
|
||||
assert_eq!(expect, vector);
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,8 @@ use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use common_error::ext::BoxedError;
|
||||
use common_function::function::FunctionRef;
|
||||
use common_function::scalars::aggregate::AggregateFunctionMetaRef;
|
||||
use common_function::scalars::FunctionRef;
|
||||
use common_query::prelude::ScalarUdf;
|
||||
use common_query::Output;
|
||||
use common_recordbatch::SendableRecordBatchStream;
|
||||
|
||||
@@ -24,9 +24,9 @@ use std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
use common_base::Plugins;
|
||||
use common_error::ext::BoxedError;
|
||||
use common_function::function::FunctionRef;
|
||||
use common_function::scalars::aggregate::AggregateFunctionMetaRef;
|
||||
use common_function::scalars::udf::create_udf;
|
||||
use common_function::scalars::FunctionRef;
|
||||
use common_query::physical_plan::{DfPhysicalPlanAdapter, PhysicalPlan, PhysicalPlanAdapter};
|
||||
use common_query::prelude::ScalarUdf;
|
||||
use common_query::Output;
|
||||
|
||||
@@ -22,8 +22,9 @@ use std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
use catalog::CatalogManagerRef;
|
||||
use common_base::Plugins;
|
||||
use common_function::function::FunctionRef;
|
||||
use common_function::function_registry::FUNCTION_REGISTRY;
|
||||
use common_function::scalars::aggregate::AggregateFunctionMetaRef;
|
||||
use common_function::scalars::{FunctionRef, FUNCTION_REGISTRY};
|
||||
use common_query::prelude::ScalarUdf;
|
||||
use common_query::Output;
|
||||
use datatypes::schema::Schema;
|
||||
|
||||
@@ -21,7 +21,8 @@ use std::task::{Context, Poll};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use common_error::ext::BoxedError;
|
||||
use common_function::scalars::{Function, FUNCTION_REGISTRY};
|
||||
use common_function::function::Function;
|
||||
use common_function::function_registry::FUNCTION_REGISTRY;
|
||||
use common_query::error::{PyUdfSnafu, UdfTempRecordBatchSnafu};
|
||||
use common_query::prelude::Signature;
|
||||
use common_query::Output;
|
||||
@@ -150,7 +151,7 @@ impl Function for PyUDF {
|
||||
|
||||
fn eval(
|
||||
&self,
|
||||
_func_ctx: common_function::scalars::function::FunctionContext,
|
||||
_func_ctx: common_function::function::FunctionContext,
|
||||
columns: &[datatypes::vectors::VectorRef],
|
||||
) -> common_query::error::Result<datatypes::vectors::VectorRef> {
|
||||
// FIXME(discord9): exec_parsed require a RecordBatch(basically a Vector+Schema), where schema can't pop out from nowhere, right?
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use common_function::scalars::{FunctionRef, FUNCTION_REGISTRY};
|
||||
use common_function::function::FunctionRef;
|
||||
use common_function::function_registry::FUNCTION_REGISTRY;
|
||||
use datafusion::arrow::array::{ArrayRef, NullArray};
|
||||
use datafusion::physical_plan::expressions;
|
||||
use datafusion_expr::ColumnarValue;
|
||||
|
||||
@@ -288,9 +288,9 @@ pub(crate) mod greptime_builtin {
|
||||
use std::sync::Arc;
|
||||
|
||||
use arrow::compute::kernels::{aggregate, boolean};
|
||||
use common_function::scalars::function::FunctionContext;
|
||||
use common_function::function::{Function, FunctionContext, FunctionRef};
|
||||
use common_function::function_registry::FUNCTION_REGISTRY;
|
||||
use common_function::scalars::math::PowFunction;
|
||||
use common_function::scalars::{Function, FunctionRef, FUNCTION_REGISTRY};
|
||||
use datafusion::arrow::datatypes::DataType as ArrowDataType;
|
||||
use datafusion::dataframe::DataFrame as DfDataFrame;
|
||||
use datafusion::physical_plan::expressions;
|
||||
|
||||
10
tests/cases/standalone/common/function/system.result
Normal file
10
tests/cases/standalone/common/function/system.result
Normal file
@@ -0,0 +1,10 @@
|
||||
-- SQLNESS REPLACE branch:\s+.+ branch: BRANCH
|
||||
-- SQLNESS REPLACE commit:\s+.+ commit: COMMIT
|
||||
-- SQLNESS REPLACE commit+\s+short:\s+.+ commit short: COMMIT SHORT
|
||||
-- SQLNESS REPLACE dirty:\s+.+ dirty: DIRTY
|
||||
-- SQLNESS REPLACE version:\s+.+ version: VERSION
|
||||
-- SQLNESS REPLACE [\s\-]+
|
||||
SELECT build();
|
||||
|
||||
++|build()|++|branch:BRANCH|commit:COMMIT|commitshort:COMMITSHORT|dirty:DIRTY|version:VERSION++
|
||||
|
||||
7
tests/cases/standalone/common/function/system.sql
Normal file
7
tests/cases/standalone/common/function/system.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
-- SQLNESS REPLACE branch:\s+.+ branch: BRANCH
|
||||
-- SQLNESS REPLACE commit:\s+.+ commit: COMMIT
|
||||
-- SQLNESS REPLACE commit+\s+short:\s+.+ commit short: COMMIT SHORT
|
||||
-- SQLNESS REPLACE dirty:\s+.+ dirty: DIRTY
|
||||
-- SQLNESS REPLACE version:\s+.+ version: VERSION
|
||||
-- SQLNESS REPLACE [\s\-]+
|
||||
SELECT build();
|
||||
Reference in New Issue
Block a user