feat: Initial support of postgresql wire protocol (#229)

* feat: initial commit of postgres protocol adapter

* initial commit of postgres server

* feat: use common_io runtime and correct testcase

* fix previous tests

* feat: adopt pgwire api changes and add support for text encoded data

* feat: initial integration with datanode

* test: add feature flag to test

* fix: resolve lint warnings

* feat: add postgres feature flags for datanode

* feat: add support for newly introduced timestamp type

* feat: adopt latest datanode changes

* fix: address clippy warning for flattern scenario

* fix: make clippy great again

* fix: address issues found in review

* chore: sort dependencies by name

* feat: adopt new Output api

* fix: return error on unsupported data types

* refactor: extract common code dealing with record batches

* fix: resolve clippy warnings

* test: adds some unit tests postgres handler

* test: correct test for cargo update

* fix: update query module name

* test: add assertion for error content
This commit is contained in:
Ning Sun
2022-09-15 21:39:05 +08:00
committed by GitHub
parent fb6153f7e0
commit e67b0eb259
17 changed files with 1277 additions and 528 deletions

View File

@@ -4,10 +4,11 @@ version = "0.1.0"
edition = "2021"
[features]
default = ["python"]
default = ["python", "postgres"]
python = [
"dep:script"
]
postgres = ["servers/postgres"]
[dependencies]
api = { path = "../api" }

View File

@@ -26,6 +26,10 @@ pub struct DatanodeOptions {
pub rpc_addr: String,
pub mysql_addr: String,
pub mysql_runtime_size: u32,
#[cfg(feature = "postgres")]
pub postgres_addr: String,
#[cfg(feature = "postgres")]
pub postgres_runtime_size: u32,
pub wal_dir: String,
pub storage: ObjectStoreConfig,
}
@@ -37,6 +41,10 @@ impl Default for DatanodeOptions {
rpc_addr: "0.0.0.0:3001".to_string(),
mysql_addr: "0.0.0.0:3306".to_string(),
mysql_runtime_size: 2,
#[cfg(feature = "postgres")]
postgres_addr: "0.0.0.0:5432".to_string(),
#[cfg(feature = "postgres")]
postgres_runtime_size: 2,
wal_dir: "/tmp/greptimedb/wal".to_string(),
storage: ObjectStoreConfig::default(),
}

View File

@@ -7,6 +7,7 @@ use common_runtime::Builder as RuntimeBuilder;
use servers::grpc::GrpcServer;
use servers::http::HttpServer;
use servers::mysql::server::MysqlServer;
use servers::postgres::PostgresServer;
use servers::server::Server;
use snafu::ResultExt;
use tokio::try_join;
@@ -20,6 +21,8 @@ pub struct Services {
http_server: HttpServer,
grpc_server: GrpcServer,
mysql_server: Box<dyn Server>,
#[cfg(feature = "postgres")]
postgres_server: Box<dyn Server>,
}
impl Services {
@@ -31,34 +34,49 @@ impl Services {
.build()
.context(error::RuntimeResourceSnafu)?,
);
#[cfg(feature = "postgres")]
let postgres_io_runtime = Arc::new(
RuntimeBuilder::default()
.worker_threads(opts.postgres_runtime_size as usize)
.thread_name("postgres-io-handlers")
.build()
.context(error::RuntimeResourceSnafu)?,
);
Ok(Self {
http_server: HttpServer::new(instance.clone()),
grpc_server: GrpcServer::new(instance.clone(), instance.clone()),
mysql_server: MysqlServer::create_server(instance, mysql_io_runtime),
mysql_server: MysqlServer::create_server(instance.clone(), mysql_io_runtime),
#[cfg(feature = "postgres")]
postgres_server: Box::new(PostgresServer::new(instance, postgres_io_runtime)),
})
}
// TODO(LFC): make servers started on demand (not starting mysql if no needed, for example)
pub async fn start(&mut self, opts: &DatanodeOptions) -> Result<()> {
let http_addr = &opts.http_addr;
let http_addr: SocketAddr = http_addr
.parse()
.context(error::ParseAddrSnafu { addr: http_addr })?;
let http_addr: SocketAddr = opts.http_addr.parse().context(error::ParseAddrSnafu {
addr: &opts.http_addr,
})?;
let grpc_addr = &opts.rpc_addr;
let grpc_addr: SocketAddr = grpc_addr
.parse()
.context(error::ParseAddrSnafu { addr: grpc_addr })?;
let grpc_addr: SocketAddr = opts.rpc_addr.parse().context(error::ParseAddrSnafu {
addr: &opts.rpc_addr,
})?;
let mysql_addr = &opts.mysql_addr;
let mysql_addr: SocketAddr = mysql_addr
.parse()
.context(error::ParseAddrSnafu { addr: mysql_addr })?;
let mysql_addr: SocketAddr = opts.mysql_addr.parse().context(error::ParseAddrSnafu {
addr: &opts.mysql_addr,
})?;
#[cfg(feature = "postgres")]
let postgres_addr: SocketAddr =
opts.postgres_addr.parse().context(error::ParseAddrSnafu {
addr: &opts.postgres_addr,
})?;
try_join!(
self.http_server.start(http_addr),
self.grpc_server.start(grpc_addr),
self.mysql_server.start(mysql_addr),
#[cfg(feature = "postgres")]
self.postgres_server.start(postgres_addr),
)
.context(error::StartServerSnafu)?;
Ok(())