Skip to content

Commit 06958cc

Browse files
authored
omdb: Add one-shot query exec to oxql subcommand (#10154)
In some cases, we may execute an `oxql` query as part of an ad hoc shell script, or have capture the queries executed in the shell history. The mandatory `reedline` shell used by the `oxql` subcommand prevents this. Add a `--execute` flag to provide a one-shot execution option to the `oxql` subcommand.
1 parent d7ebf7f commit 06958cc

3 files changed

Lines changed: 64 additions & 13 deletions

File tree

dev-tools/omdb/src/bin/omdb/oxql.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ pub struct OxqlArgs {
3838
/// Print the total elapsed query duration.
3939
#[clap(long = "elapsed")]
4040
print_elapsed: bool,
41+
42+
/// Execute the query and exit.
43+
#[clap(long, short, value_name = "QUERY")]
44+
execute: Option<String>,
4145
}
4246

4347
impl OxqlArgs {
@@ -54,13 +58,24 @@ impl OxqlArgs {
5458
print_elapsed: self.print_elapsed,
5559
};
5660

57-
oxql::shell(
58-
native_addr.ip(),
59-
native_addr.port(),
60-
log.new(slog::o!("component" => "clickhouse-client")),
61-
opts,
62-
)
63-
.await
61+
if let Some(query) = &self.execute {
62+
oxql::exec_query(
63+
native_addr.ip(),
64+
native_addr.port(),
65+
log.new(slog::o!("component" => "clickhouse-client")),
66+
opts,
67+
query.to_owned(),
68+
)
69+
.await
70+
} else {
71+
oxql::shell(
72+
native_addr.ip(),
73+
native_addr.port(),
74+
log.new(slog::o!("component" => "clickhouse-client")),
75+
opts,
76+
)
77+
.await
78+
}
6479
}
6580

6681
/// Resolve the ClickHouse native TCP socket address.

dev-tools/omdb/tests/usage_errors.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,7 @@ Options:
12051205
--summaries Print summaries of each SQL query run against the database
12061206
--elapsed Print the total elapsed query duration
12071207
--color <COLOR> Color output [default: auto] [possible values: auto, always, never]
1208+
-e, --execute <QUERY> Execute the query and exit
12081209
-h, --help Print help
12091210

12101211
Connection Options:

oximeter/db/src/shells/oxql.rs

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,7 @@ pub async fn shell(
3737
opts: ShellOptions,
3838
) -> anyhow::Result<()> {
3939
// Create the client.
40-
let client = make_client(address, port, &log).await?;
41-
42-
// A workaround to ensure the client has all available timeseries when the
43-
// shell starts.
44-
let dummy = "foo:bar".parse().unwrap();
45-
let _ = client.schema_for_timeseries(&dummy).await;
40+
let client = make_oxql_client(address, port, &log).await?;
4641

4742
// Create the line-editor.
4843
let mut ed = Reedline::create();
@@ -157,6 +152,46 @@ pub async fn shell(
157152
}
158153
}
159154

155+
/// Execute the provided OxQL query.
156+
pub async fn exec_query(
157+
address: IpAddr,
158+
port: u16,
159+
log: Logger,
160+
opts: ShellOptions,
161+
statement: String,
162+
) -> anyhow::Result<()> {
163+
// Create the client.
164+
let client = make_oxql_client(address, port, &log).await?;
165+
166+
let result = client
167+
.oxql_query(
168+
statement.trim().trim_end_matches(';'),
169+
QueryAuthzScope::Fleet,
170+
)
171+
.await?;
172+
173+
print_tables(&result.tables);
174+
println!();
175+
print_query_summary(&result, opts.print_elapsed, opts.print_summaries);
176+
177+
Ok(())
178+
}
179+
180+
/// Create an OxQL client and prime its schema cache.
181+
async fn make_oxql_client(
182+
address: IpAddr,
183+
port: u16,
184+
log: &Logger,
185+
) -> anyhow::Result<Client> {
186+
let client = make_client(address, port, log).await?;
187+
188+
// Workaround to ensure the client has all available timeseries.
189+
let dummy = "foo:bar".parse().unwrap();
190+
let _ = client.schema_for_timeseries(&dummy).await;
191+
192+
Ok(client)
193+
}
194+
160195
/// Describe a single timeseries.
161196
async fn describe_timeseries(
162197
client: &Client,

0 commit comments

Comments
 (0)