-
-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathderby.rs
More file actions
109 lines (98 loc) · 4.2 KB
/
Copy pathderby.rs
File metadata and controls
109 lines (98 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use std::path::PathBuf;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use snafu::{OptionExt, ResultExt, Snafu};
use crate::{
database_connections::{
TemplatingMechanism,
drivers::jdbc::{JdbcDatabaseConnection, JdbcDatabaseConnectionDetails},
},
utils::OptionExt as _,
};
/// Sadly the Derby driver class name is a bit complicated, e.g. for HMS up to 4.1.x we used
/// `org.apache.derby.jdbc.EmbeddedDriver`, for HMS 4.2.x we used
/// `org.apache.derby.iapi.jdbc.AutoloadedDriver`.
pub const DERBY_JDBC_DRIVER_CLASS: &str = "org.apache.derby.jdbc.EmbeddedDriver";
#[derive(Debug, Snafu)]
pub enum Error {
#[snafu(display("failed to parse connection URL"))]
ParseConnectionUrl { source: url::ParseError },
#[snafu(display("invalid derby database location, likely as it contains non-utf8 characters"))]
NonUtf8Location { location: PathBuf },
}
/// Connection settings for an embedded [Apache Derby](https://db.apache.org/derby/) database.
///
/// Derby is an embedded, file-based Java database engine that requires no separate server process.
/// It is typically used for development, testing, or as a lightweight metastore backend (e.g. for
/// Apache Hive).
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DerbyConnection {
/// Path on the filesystem where Derby stores its database files.
///
/// If not specified, defaults to `/tmp/derby/{unique_database_name}/derby.db`.
/// The `{unique_database_name}` part is automatically handled by the operator and is added to
/// prevent clashing database files. The `create=true` flag is always appended to the JDBC URL,
/// so the database is created automatically if it does not yet exist at this location.
pub location: Option<PathBuf>,
}
impl JdbcDatabaseConnection for DerbyConnection {
fn jdbc_connection_details_with_templating(
&self,
unique_database_name: &str,
_templating_mechanism: &TemplatingMechanism,
) -> Result<JdbcDatabaseConnectionDetails, crate::database_connections::Error> {
let location = self.location(unique_database_name)?;
let connection_url = format!("jdbc:derby:{location};create=true")
.parse()
.context(ParseConnectionUrlSnafu)?;
Ok(JdbcDatabaseConnectionDetails {
driver: DERBY_JDBC_DRIVER_CLASS.to_owned(),
connection_url,
username_env: None,
password_env: None,
})
}
}
impl DerbyConnection {
/// Returns the JDBC connection URL in a format such as
/// `jdbc:derby://localhost:1527//opt/var/druid_state/derby;create=true`.
///
/// E.g. according to the [Druid docs](https://druid.apache.org/docs/latest/design/metadata-storage/#derby)
/// we should configure something like
/// `jdbc:derby://localhost:1527//opt/var/druid_state/derby;create=true`.
///
/// Druid actually starts a Derby instance, which listens on `127.0.0.1:1527`. The schema seems
/// to be the filesystem location.
pub fn jdbc_connection_details_for_network_access(
&self,
unique_database_name: &str,
host_part: &str,
) -> Result<JdbcDatabaseConnectionDetails, crate::database_connections::Error> {
let location = self.location(unique_database_name)?;
let connection_url = format!("jdbc:derby://{host_part}/{location};create=true")
.parse()
.context(ParseConnectionUrlSnafu)?;
Ok(JdbcDatabaseConnectionDetails {
driver: DERBY_JDBC_DRIVER_CLASS.to_owned(),
connection_url,
username_env: None,
password_env: None,
})
}
/// Returns the configured [`Self::location`] or a sensible default value
fn location(
&self,
unique_database_name: &str,
) -> Result<String, crate::database_connections::Error> {
let location = self.location.as_ref_or_else(|| {
PathBuf::from(format!("/tmp/derby/{unique_database_name}/derby.db"))
});
Ok(location
.to_str()
.with_context(|| NonUtf8LocationSnafu {
location: location.to_path_buf(),
})?
.to_owned())
}
}