Files
greptimedb/src/frontend/src/instance/influxdb.rs
Lei, Huang fae331d2ba feat: Move create table logic to frontend (#455)
* refactor: dependency, from frontend depends on datanode to datanode depends on frontend

* wip: start frontend in datanode

* wip: migrate create database to frontend

* wip: impl alter table

* fix: CR comments

* feat: add table id and region ids field to CreateExpr

* chore: rebase develop

* refactor: frontend catalog should set from datanode

* feat: gRPC AddColumn request support add multi columns

* wip: move create table and create-on-insertion to frontend

* wip: error handling

* fix: some unit tests

* fix: all unit tests

* chore: merge develop

* feat: add create/alter-on-insertion to dist_insert/sql_dist_insert

* fix: add region number/catalog/schema to InsertExpr

* feat: add handle_create_table/handle_create_database...

* fix: remove catalog from insert expr

* fix: CR comments

* fix: when running in standalone mode, mysql opts and postgres opts should pass to frontend so that auctually running service can change the port to listen on

* refactor: add a standalone subcommand, move frontend start stuff to cmd package

* chore: optimize create table failure logs

* docs: change readme

* docs: update readme
2022-11-14 10:54:35 +08:00

80 lines
2.6 KiB
Rust

use api::v1::InsertExpr;
use async_trait::async_trait;
use common_error::prelude::BoxedError;
use servers::influxdb::InfluxdbRequest;
use servers::{error as server_error, query_handler::InfluxdbLineProtocolHandler};
use snafu::{OptionExt, ResultExt};
use table::requests::InsertRequest;
use crate::error;
use crate::error::Result;
use crate::frontend::Mode;
use crate::instance::Instance;
#[async_trait]
impl InfluxdbLineProtocolHandler for Instance {
async fn exec(&self, request: &InfluxdbRequest) -> servers::error::Result<()> {
match self.mode {
Mode::Standalone => {
let exprs: Vec<InsertExpr> = request.try_into()?;
self.handle_inserts(&exprs)
.await
.map_err(BoxedError::new)
.context(server_error::ExecuteQuerySnafu {
query: &request.lines,
})?;
}
Mode::Distributed => {
self.dist_insert(request.try_into()?)
.await
.map_err(BoxedError::new)
.context(server_error::ExecuteInsertSnafu {
msg: "execute insert failed",
})?;
}
}
Ok(())
}
}
impl Instance {
pub(crate) async fn dist_insert(&self, inserts: Vec<InsertRequest>) -> Result<usize> {
let mut joins = Vec::with_capacity(inserts.len());
for insert in inserts {
let self_clone = self.clone();
let insert_batch = crate::table::insert::insert_request_to_insert_batch(&insert)?;
self.create_or_alter_table_on_demand(
&insert.catalog_name,
&insert.schema_name,
&insert.table_name,
&[insert_batch],
)
.await?;
// TODO(fys): need a separate runtime here
let join = tokio::spawn(async move {
let catalog = self_clone.get_catalog(&insert.catalog_name)?;
let schema = Self::get_schema(catalog, &insert.schema_name)?;
let table = schema
.table(&insert.table_name)
.context(error::CatalogSnafu)?
.context(error::TableNotFoundSnafu {
table_name: &insert.table_name,
})?;
table.insert(insert).await.context(error::TableSnafu)
});
joins.push(join);
}
let mut affected = 0;
for join in joins {
affected += join.await.context(error::JoinTaskSnafu)??;
}
Ok(affected)
}
}