mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-01-04 04:12:55 +00:00
feat: avoid using vector to get default value (#2323)
This commit is contained in:
@@ -54,6 +54,18 @@ impl Timestamp {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates current timestamp in specific time `unit`.
|
||||
pub fn current_time(unit: TimeUnit) -> Timestamp {
|
||||
let now = chrono::Utc::now();
|
||||
let value = match unit {
|
||||
TimeUnit::Second => now.timestamp(),
|
||||
TimeUnit::Millisecond => now.timestamp_millis(),
|
||||
TimeUnit::Microsecond => now.timestamp_micros(),
|
||||
TimeUnit::Nanosecond => now.timestamp_nanos(),
|
||||
};
|
||||
Timestamp { value, unit }
|
||||
}
|
||||
|
||||
/// Subtracts a duration from timestamp.
|
||||
/// # Note
|
||||
/// The result time unit remains unchanged even if `duration` has a different unit with `self`.
|
||||
|
||||
@@ -161,8 +161,21 @@ impl ColumnSchema {
|
||||
///
|
||||
/// If the column is `NOT NULL` but doesn't has `DEFAULT` value supplied, returns `Ok(None)`.
|
||||
pub fn create_default(&self) -> Result<Option<Value>> {
|
||||
self.create_default_vector(1)
|
||||
.map(|vec_ref_option| vec_ref_option.map(|vec_ref| vec_ref.get(0)))
|
||||
match &self.default_constraint {
|
||||
Some(c) => c
|
||||
.create_default(&self.data_type, self.is_nullable)
|
||||
.map(Some),
|
||||
None => {
|
||||
if self.is_nullable {
|
||||
// No default constraint, use null as default value.
|
||||
ColumnDefaultConstraint::null_value()
|
||||
.create_default(&self.data_type, self.is_nullable)
|
||||
.map(Some)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use common_time::util;
|
||||
use common_time::{util, Timestamp};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use snafu::{ensure, ResultExt};
|
||||
|
||||
@@ -150,6 +150,28 @@ impl ColumnDefaultConstraint {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a default value for given `data_type`.
|
||||
///
|
||||
/// If `is_nullable` is `true`, then this method would returns error if the created
|
||||
/// default value is null.
|
||||
pub fn create_default(&self, data_type: &ConcreteDataType, is_nullable: bool) -> Result<Value> {
|
||||
match self {
|
||||
ColumnDefaultConstraint::Function(expr) => {
|
||||
// Functions should also ensure its return value is not null when
|
||||
// is_nullable is true.
|
||||
match &expr[..] {
|
||||
CURRENT_TIMESTAMP => create_current_timestamp(data_type),
|
||||
_ => error::UnsupportedDefaultExprSnafu { expr }.fail(),
|
||||
}
|
||||
}
|
||||
ColumnDefaultConstraint::Value(v) => {
|
||||
ensure!(is_nullable || !v.is_null(), error::NullDefaultSnafu);
|
||||
|
||||
Ok(v.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this constraint might creates NULL.
|
||||
fn maybe_null(&self) -> bool {
|
||||
// Once we support more functions, we may return true if given function
|
||||
@@ -158,6 +180,18 @@ impl ColumnDefaultConstraint {
|
||||
}
|
||||
}
|
||||
|
||||
fn create_current_timestamp(data_type: &ConcreteDataType) -> Result<Value> {
|
||||
let Some(timestamp_type) = data_type.as_timestamp() else {
|
||||
return error::DefaultValueTypeSnafu {
|
||||
reason: format!("Not support to assign current timestamp to {data_type:?} type"),
|
||||
}
|
||||
.fail();
|
||||
};
|
||||
|
||||
let unit = timestamp_type.unit();
|
||||
Ok(Value::Timestamp(Timestamp::current_time(unit)))
|
||||
}
|
||||
|
||||
fn create_current_timestamp_vector(
|
||||
data_type: &ConcreteDataType,
|
||||
num_rows: usize,
|
||||
@@ -246,7 +280,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_default_vector_by_value() {
|
||||
fn test_create_default_by_value() {
|
||||
let constraint = ColumnDefaultConstraint::Value(Value::Int32(10));
|
||||
let data_type = ConcreteDataType::int32_datatype();
|
||||
let v = constraint
|
||||
@@ -254,55 +288,65 @@ mod tests {
|
||||
.unwrap();
|
||||
let expect: VectorRef = Arc::new(Int32Vector::from_values(vec![10; 4]));
|
||||
assert_eq!(expect, v);
|
||||
let v = constraint.create_default(&data_type, false).unwrap();
|
||||
assert_eq!(Value::Int32(10), v);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_default_vector_by_func() {
|
||||
let constraint = ColumnDefaultConstraint::Function(CURRENT_TIMESTAMP.to_string());
|
||||
let check_value = |v| {
|
||||
assert!(
|
||||
matches!(v, Value::Timestamp(_)),
|
||||
"v {:?} is not timestamp",
|
||||
v
|
||||
);
|
||||
};
|
||||
let check_vector = |v: VectorRef| {
|
||||
assert_eq!(4, v.len());
|
||||
assert!(
|
||||
matches!(v.get(0), Value::Timestamp(_)),
|
||||
"v {:?} is not timestamp",
|
||||
v.get(0)
|
||||
);
|
||||
};
|
||||
|
||||
// Timestamp type.
|
||||
let data_type = ConcreteDataType::timestamp_millisecond_datatype();
|
||||
let v = constraint
|
||||
.create_default_vector(&data_type, false, 4)
|
||||
.unwrap();
|
||||
assert_eq!(4, v.len());
|
||||
assert!(
|
||||
matches!(v.get(0), Value::Timestamp(_)),
|
||||
"v {:?} is not timestamp",
|
||||
v.get(0)
|
||||
);
|
||||
check_vector(v);
|
||||
|
||||
let v = constraint.create_default(&data_type, false).unwrap();
|
||||
check_value(v);
|
||||
|
||||
let data_type = ConcreteDataType::timestamp_second_datatype();
|
||||
let v = constraint
|
||||
.create_default_vector(&data_type, false, 4)
|
||||
.unwrap();
|
||||
assert_eq!(4, v.len());
|
||||
assert!(
|
||||
matches!(v.get(0), Value::Timestamp(_)),
|
||||
"v {:?} is not timestamp",
|
||||
v.get(0)
|
||||
);
|
||||
check_vector(v);
|
||||
|
||||
let v = constraint.create_default(&data_type, false).unwrap();
|
||||
check_value(v);
|
||||
|
||||
let data_type = ConcreteDataType::timestamp_microsecond_datatype();
|
||||
let v = constraint
|
||||
.create_default_vector(&data_type, false, 4)
|
||||
.unwrap();
|
||||
assert_eq!(4, v.len());
|
||||
assert!(
|
||||
matches!(v.get(0), Value::Timestamp(_)),
|
||||
"v {:?} is not timestamp",
|
||||
v.get(0)
|
||||
);
|
||||
check_vector(v);
|
||||
|
||||
let v = constraint.create_default(&data_type, false).unwrap();
|
||||
check_value(v);
|
||||
|
||||
let data_type = ConcreteDataType::timestamp_nanosecond_datatype();
|
||||
let v = constraint
|
||||
.create_default_vector(&data_type, false, 4)
|
||||
.unwrap();
|
||||
assert_eq!(4, v.len());
|
||||
assert!(
|
||||
matches!(v.get(0), Value::Timestamp(_)),
|
||||
"v {:?} is not timestamp",
|
||||
v.get(0)
|
||||
);
|
||||
check_vector(v);
|
||||
|
||||
let v = constraint.create_default(&data_type, false).unwrap();
|
||||
check_value(v);
|
||||
|
||||
// Int64 type.
|
||||
let data_type = ConcreteDataType::int64_datatype();
|
||||
@@ -321,6 +365,7 @@ mod tests {
|
||||
assert!(constraint
|
||||
.create_default_vector(&data_type, false, 4)
|
||||
.is_err());
|
||||
assert!(constraint.create_default(&data_type, false).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user