diff --git a/server/src/grpc/storage_service/route.rs b/server/src/grpc/storage_service/route.rs index a38f4854e9..ad22ef5927 100644 --- a/server/src/grpc/storage_service/route.rs +++ b/server/src/grpc/storage_service/route.rs @@ -2,7 +2,12 @@ //! Route handler -use ceresdbproto::storage::{RouteRequest, RouteResponse}; +use std::collections::HashMap; + +use ceresdbproto::storage::{Route, RouteRequest, RouteResponse}; +use error::ErrNoCause; +use http::StatusCode; +use snafu::OptionExt; use crate::grpc::storage_service::{ error::{self, Result}, @@ -13,11 +18,61 @@ pub async fn handle_route( ctx: &HandlerContext<'_, Q>, req: RouteRequest, ) -> Result { + // TODO: the case sensitive mode with quoted is not supported now, all table + // name will be converted to lowercase. + + // Get normalized metrics to original one's mapping. + let normalized_to_origin: HashMap<_, _> = req + .metrics + .iter() + .enumerate() + .map(|(idx, metric)| (metric.to_ascii_lowercase(), idx)) + .collect(); + let mut origins = req.metrics; + + // Route using normalized metrics. + let normalized_metrics: Vec<_> = normalized_to_origin + .iter() + .map(|(k, _)| k.clone()) + .collect(); + let req = RouteRequest { + metrics: normalized_metrics, + }; + + // Replace the normalized metrics in response to origin ones to avoiding + // exposing this behavior to client. let routes = ctx.router.route(ctx.tenant(), req).await?; + let mut routes_with_origins = Vec::with_capacity(routes.len()); + let origins_len = origins.len(); + for route in routes { + let idx = normalized_to_origin + .get(&route.metric) + .with_context(|| ErrNoCause { + code: StatusCode::INTERNAL_SERVER_ERROR, + msg: format!( + "unknown normalized metric name while finding its origin, metric:{}", + route.metric + ), + })?; + + let origin = origins.get_mut(*idx).with_context(|| ErrNoCause { + code: StatusCode::INTERNAL_SERVER_ERROR, + msg: format!( + "impossible to find nothing through idx, idx:{}, origins len:{}", + idx, origins_len + ), + })?; + + routes_with_origins.push(Route { + metric: std::mem::take(origin), + endpoint: route.endpoint, + ext: route.ext, + }); + } let resp = RouteResponse { header: Some(error::build_ok_header()), - routes, + routes: routes_with_origins, }; Ok(resp) diff --git a/server/src/grpc/storage_service/write.rs b/server/src/grpc/storage_service/write.rs index 17ccaf7068..9368b335b0 100644 --- a/server/src/grpc/storage_service/write.rs +++ b/server/src/grpc/storage_service/write.rs @@ -115,15 +115,15 @@ async fn write_request_to_insert_plan( let mut plan_vec = Vec::with_capacity(write_request.metrics.len()); for write_metric in write_request.metrics { - let table_name = &write_metric.metric; - let mut table = try_get_table(ctx, table_name)?; + let normalized_table_name = &write_metric.metric.to_ascii_lowercase(); + let mut table = try_get_table(ctx, normalized_table_name)?; if table.is_none() { if let Some(config) = ctx.schema_config { if config.auto_create_tables { create_table(ctx, &write_metric, request_id).await?; // try to get table again - table = try_get_table(ctx, table_name)?; + table = try_get_table(ctx, normalized_table_name)?; } } } @@ -139,7 +139,7 @@ async fn write_request_to_insert_plan( msg: format!( "Table not found, tenant:{}, table:{}", ctx.tenant(), - table_name + normalized_table_name ), } .fail(); diff --git a/sql/src/ast.rs b/sql/src/ast.rs index d2a6fe1264..b9fbec0570 100644 --- a/sql/src/ast.rs +++ b/sql/src/ast.rs @@ -3,7 +3,7 @@ //! SQL statement use sqlparser::ast::{ - ColumnDef, Ident, ObjectName, SqlOption, Statement as SqlStatement, TableConstraint, + ColumnDef, ObjectName, SqlOption, Statement as SqlStatement, TableConstraint, }; /// Statement representations @@ -33,14 +33,6 @@ impl TableName { pub fn is_empty(&self) -> bool { self.0 .0.is_empty() } - - // Normalize an identifer to a lowercase string unless the identifier is quoted. - fn normalize_ident(id: &Ident) -> String { - match id.quote_style { - Some(_) => id.value.clone(), - None => id.value.to_ascii_lowercase(), - } - } } impl ToString for TableName { @@ -48,7 +40,7 @@ impl ToString for TableName { self.0 .0 .iter() - .map(Self::normalize_ident) + .map(|id| id.value.to_ascii_lowercase()) .collect::>() .join(".") }