mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-10-25 05:12:27 +00:00
chore(deps): upgrade sqlx to 0.9 to pick up webpki-roots 1.0.10 (#9862)
sqlx 0.8 pins the unmaintained webpki-roots 0.26 line for its rustls trust store, which still contains the recently compromised e-Tugra CA root. Upgrading sqlx to 0.9 switches its dependency to webpki-roots 1.x, and the lockfile now resolves to 1.0.10 where the distrusted root has been removed from the compiled-in Mozilla trust store. sqlx 0.9 requires dynamic SQL strings to be explicitly audited via the new SqlSafeStr trait: only &'static str literals are accepted as-is. All affected call sites (MySQL KV backend, MySQL election, integration tests and fuzz targets) now wrap their internally generated SQL templates in AssertSqlSafe; the wrapped SQL is built from operator config or test-local identifiers only, and dynamic data keeps flowing through bind parameters. The mysql-rsa feature is enabled alongside mysql to preserve 0.8 authentication behavior: sqlx 0.9 gates non-TLS RSA password auth (caching_sha2_password / sha256_password) behind it. Signed-off-by: Ning Sun <sunning@greptime.com>
This commit is contained in:
Generated
+452
-121
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -250,7 +250,7 @@ similar-asserts = "1.6.0"
|
||||
smallvec = { version = "1", features = ["serde"] }
|
||||
snafu = "0.8"
|
||||
sqlparser = { version = "0.62.0", default-features = false, features = ["std", "visitor", "serde"] }
|
||||
sqlx = { version = "0.8", default-features = false, features = [
|
||||
sqlx = { version = "0.9", default-features = false, features = [
|
||||
"any",
|
||||
"macros",
|
||||
"json",
|
||||
|
||||
@@ -81,6 +81,7 @@ serde_with.workspace = true
|
||||
snafu.workspace = true
|
||||
sqlx = { workspace = true, features = [
|
||||
"mysql",
|
||||
"mysql-rsa",
|
||||
"chrono",
|
||||
], optional = true }
|
||||
store-api.workspace = true
|
||||
|
||||
@@ -22,7 +22,7 @@ use snafu::{OptionExt, ResultExt, ensure};
|
||||
use sqlx::mysql::{MySqlArguments, MySqlRow};
|
||||
use sqlx::pool::PoolConnection;
|
||||
use sqlx::query::Query;
|
||||
use sqlx::{MySql, MySqlPool, MySqlTransaction, Row};
|
||||
use sqlx::{AssertSqlSafe, MySql, MySqlPool, MySqlTransaction, Row};
|
||||
use tokio::sync::{Mutex, MutexGuard, broadcast};
|
||||
use tokio::time::MissedTickBehavior;
|
||||
|
||||
@@ -38,6 +38,17 @@ use crate::error::{
|
||||
};
|
||||
use crate::key::{CANDIDATES_ROOT, ELECTION_KEY};
|
||||
|
||||
/// Builds a [`Query`] from a dynamic SQL template.
|
||||
///
|
||||
/// sqlx 0.9 requires `&'static str` or [`AssertSqlSafe`] to reject unaudited
|
||||
/// dynamic SQL strings. The templates here are generated by
|
||||
/// [`ElectionSqlFactory`] from the configured table name (operator config,
|
||||
/// not user input), and all dynamic data is passed via bind parameters,
|
||||
/// so it is safe to mark them with [`AssertSqlSafe`].
|
||||
fn template_query(sql: &str) -> Query<'_, MySql, MySqlArguments> {
|
||||
sqlx::query(AssertSqlSafe(sql))
|
||||
}
|
||||
|
||||
struct ElectionSqlFactory<'a> {
|
||||
table_name: &'a str,
|
||||
}
|
||||
@@ -268,11 +279,11 @@ impl ElectionMysqlClient {
|
||||
|
||||
async fn ensure_table_exists(&mut self) -> Result<()> {
|
||||
let create_table_sql = self.create_table_sql();
|
||||
let query = sqlx::query(&create_table_sql);
|
||||
let query = template_query(&create_table_sql);
|
||||
self.execute(query, &create_table_sql).await?;
|
||||
// Insert at least one row for `SELECT * FOR UPDATE` to work.
|
||||
let insert_once_sql = self.insert_once_sql();
|
||||
let query = sqlx::query(&insert_once_sql);
|
||||
let query = template_query(&insert_once_sql);
|
||||
self.execute(query, &insert_once_sql).await?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -324,7 +335,7 @@ impl ElectionMysqlClient {
|
||||
/// if `current` is `None`.
|
||||
async fn check_version(&mut self, sql: &str) -> Result<()> {
|
||||
// Check if the MySQL version is supported.
|
||||
let query = sqlx::query(sql);
|
||||
let query = template_query(sql);
|
||||
// Safety: `maybe_init_client` ensures `current` is not `None`.
|
||||
let client = self.current.as_mut().unwrap();
|
||||
let row = tokio::time::timeout(self.execution_timeout, query.fetch_one(&mut **client))
|
||||
@@ -692,7 +703,7 @@ impl MySqlElection {
|
||||
executor: &mut Executor<'_>,
|
||||
) -> Result<Option<Lease>> {
|
||||
let key = key.as_bytes();
|
||||
let query = sqlx::query(&self.sql_set.get_value_with_lease).bind(key);
|
||||
let query = template_query(&self.sql_set.get_value_with_lease).bind(key);
|
||||
let res = executor
|
||||
.query(query, &self.sql_set.get_value_with_lease)
|
||||
.await?;
|
||||
@@ -728,7 +739,7 @@ impl MySqlElection {
|
||||
executor: &mut Executor<'_>,
|
||||
) -> Result<(Vec<(String, Timestamp)>, Timestamp)> {
|
||||
let key_prefix = format!("{}%", key_prefix).as_bytes().to_vec();
|
||||
let query = sqlx::query(&self.sql_set.get_value_with_lease_by_prefix).bind(key_prefix);
|
||||
let query = template_query(&self.sql_set.get_value_with_lease_by_prefix).bind(key_prefix);
|
||||
let res = executor
|
||||
.query(query, &self.sql_set.get_value_with_lease_by_prefix)
|
||||
.await?;
|
||||
@@ -765,7 +776,7 @@ impl MySqlElection {
|
||||
let prev = prev.as_bytes();
|
||||
let updated = updated.as_bytes();
|
||||
|
||||
let query = sqlx::query(&self.sql_set.update_value_with_lease)
|
||||
let query = template_query(&self.sql_set.update_value_with_lease)
|
||||
.bind(updated)
|
||||
.bind(lease_ttl as f64)
|
||||
.bind(key)
|
||||
@@ -794,7 +805,7 @@ impl MySqlElection {
|
||||
) -> Result<bool> {
|
||||
let key = key.as_bytes();
|
||||
let lease_ttl_secs = lease_ttl_secs as f64;
|
||||
let query = sqlx::query(&self.sql_set.put_value_with_lease)
|
||||
let query = template_query(&self.sql_set.put_value_with_lease)
|
||||
.bind(key)
|
||||
.bind(value)
|
||||
.bind(lease_ttl_secs);
|
||||
@@ -808,7 +819,7 @@ impl MySqlElection {
|
||||
/// Caution: Should only delete the key if the lease is expired.
|
||||
async fn delete_value(&self, key: &str, executor: &mut Executor<'_>) -> Result<bool> {
|
||||
let key = key.as_bytes();
|
||||
let query = sqlx::query(&self.sql_set.delete_value).bind(key);
|
||||
let query = template_query(&self.sql_set.delete_value).bind(key);
|
||||
let res = executor.execute(query, &self.sql_set.delete_value).await?;
|
||||
|
||||
Ok(res == 1)
|
||||
@@ -837,7 +848,7 @@ impl MySqlElection {
|
||||
let mut client = self.client.lock().await;
|
||||
let txn = client.transaction().await?;
|
||||
let mut executor = Executor::Txn(txn);
|
||||
let query = sqlx::query(&self.sql_set.campaign);
|
||||
let query = template_query(&self.sql_set.campaign);
|
||||
executor.query(query, &self.sql_set.campaign).await?;
|
||||
// Safety: Checked if lease is not None above.
|
||||
self.renew_lease(executor, lease.unwrap()).await?;
|
||||
@@ -858,7 +869,7 @@ impl MySqlElection {
|
||||
let mut client = self.client.lock().await;
|
||||
let txn = client.transaction().await?;
|
||||
let mut executor = Executor::Txn(txn);
|
||||
let query = sqlx::query(&self.sql_set.campaign);
|
||||
let query = template_query(&self.sql_set.campaign);
|
||||
executor.query(query, &self.sql_set.campaign).await?;
|
||||
self.elected(executor, lease).await?;
|
||||
}
|
||||
@@ -869,7 +880,7 @@ impl MySqlElection {
|
||||
let mut client = self.client.lock().await;
|
||||
let txn = client.transaction().await?;
|
||||
let mut executor = Executor::Txn(txn);
|
||||
let query = sqlx::query(&self.sql_set.campaign);
|
||||
let query = template_query(&self.sql_set.campaign);
|
||||
executor.query(query, &self.sql_set.campaign).await?;
|
||||
// Safety: Checked if lease is not None above.
|
||||
self.renew_lease(executor, lease.unwrap()).await?;
|
||||
@@ -1027,7 +1038,7 @@ mod tests {
|
||||
async fn drop_table(client: &Mutex<ElectionMysqlClient>, table_name: &str) {
|
||||
let mut client = client.lock().await;
|
||||
let sql = format!("DROP TABLE IF EXISTS `{}`;", table_name);
|
||||
client.execute(sqlx::query(&sql), &sql).await.unwrap();
|
||||
client.execute(template_query(&sql), &sql).await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -1052,7 +1063,7 @@ mod tests {
|
||||
let txn = a.transaction().await.unwrap();
|
||||
let mut executor = Executor::Txn(txn);
|
||||
let raw_query = format!("SELECT * FROM `{}` FOR UPDATE;", table_name);
|
||||
let query = sqlx::query(&raw_query);
|
||||
let query = template_query(&raw_query);
|
||||
let _ = executor.query(query, &raw_query).await.unwrap();
|
||||
}
|
||||
|
||||
@@ -1258,7 +1269,7 @@ mod tests {
|
||||
let txn = client.transaction().await.unwrap();
|
||||
let mut executor = Executor::Txn(txn);
|
||||
let raw_query = format!("SELECT * FROM `{}` FOR UPDATE;", table_name);
|
||||
let query = sqlx::query(&raw_query);
|
||||
let query = template_query(&raw_query);
|
||||
let _ = executor.query(query, &raw_query).await.unwrap();
|
||||
election.elected(executor, expected_lease).await
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ use regex::Regex;
|
||||
use snafu::{OptionExt, ResultExt};
|
||||
use sqlx::mysql::MySqlRow;
|
||||
use sqlx::pool::Pool;
|
||||
use sqlx::{MySql, MySqlPool, Row, Transaction as MySqlTransaction};
|
||||
use sqlx::{AssertSqlSafe, MySql, MySqlPool, Row, Transaction as MySqlTransaction};
|
||||
use strum::AsRefStr;
|
||||
|
||||
use crate::error::{
|
||||
@@ -264,7 +264,9 @@ impl Executor for MySqlClient {
|
||||
}
|
||||
|
||||
async fn query(&mut self, raw_query: &str, params: &[&Vec<u8>]) -> Result<Vec<KeyValue>> {
|
||||
let query = sqlx::query(raw_query);
|
||||
// Safety: `raw_query` is generated by `MySqlTemplateSet`, and all dynamic data
|
||||
// is passed via bind parameters.
|
||||
let query = sqlx::query(AssertSqlSafe(raw_query));
|
||||
let query = params.iter().fold(query, |query, param| query.bind(param));
|
||||
let rows = query
|
||||
.fetch_all(&**self)
|
||||
@@ -274,7 +276,9 @@ impl Executor for MySqlClient {
|
||||
}
|
||||
|
||||
async fn execute(&mut self, raw_query: &str, params: &[&Vec<u8>]) -> Result<()> {
|
||||
let query = sqlx::query(raw_query);
|
||||
// Safety: `raw_query` is generated by `MySqlTemplateSet`, and all dynamic data
|
||||
// is passed via bind parameters.
|
||||
let query = sqlx::query(AssertSqlSafe(raw_query));
|
||||
let query = params.iter().fold(query, |query, param| query.bind(param));
|
||||
query
|
||||
.execute(&**self)
|
||||
@@ -303,7 +307,9 @@ impl Executor for MySqlClient {
|
||||
#[async_trait::async_trait]
|
||||
impl Transaction<'_> for MySqlTxnClient {
|
||||
async fn query(&mut self, raw_query: &str, params: &[&Vec<u8>]) -> Result<Vec<KeyValue>> {
|
||||
let query = sqlx::query(raw_query);
|
||||
// Safety: `raw_query` is generated by `MySqlTemplateSet`, and all dynamic data
|
||||
// is passed via bind parameters.
|
||||
let query = sqlx::query(AssertSqlSafe(raw_query));
|
||||
let query = params.iter().fold(query, |query, param| query.bind(param));
|
||||
// As said in https://docs.rs/sqlx/latest/sqlx/trait.Executor.html, we need a `&mut *transaction`. Weird.
|
||||
let rows = query
|
||||
@@ -314,7 +320,9 @@ impl Transaction<'_> for MySqlTxnClient {
|
||||
}
|
||||
|
||||
async fn execute(&mut self, raw_query: &str, params: &[&Vec<u8>]) -> Result<()> {
|
||||
let query = sqlx::query(raw_query);
|
||||
// Safety: `raw_query` is generated by `MySqlTemplateSet`, and all dynamic data
|
||||
// is passed via bind parameters.
|
||||
let query = sqlx::query(AssertSqlSafe(raw_query));
|
||||
let query = params.iter().fold(query, |query, param| query.bind(param));
|
||||
// As said in https://docs.rs/sqlx/latest/sqlx/trait.Executor.html, we need a `&mut *transaction`. Weird.
|
||||
query
|
||||
@@ -562,12 +570,14 @@ impl MySqlStore {
|
||||
pool: &Pool<MySql>,
|
||||
sql_template_set: &MySqlTemplateSet,
|
||||
) -> Result<Option<String>> {
|
||||
let row = sqlx::query(&sql_template_set.show_create_table_statement)
|
||||
.fetch_optional(pool)
|
||||
.await
|
||||
.with_context(|_| MySqlExecutionSnafu {
|
||||
sql: sql_template_set.show_create_table_statement.clone(),
|
||||
})?;
|
||||
let row = sqlx::query(AssertSqlSafe(
|
||||
sql_template_set.show_create_table_statement.as_str(),
|
||||
))
|
||||
.fetch_optional(pool)
|
||||
.await
|
||||
.with_context(|_| MySqlExecutionSnafu {
|
||||
sql: sql_template_set.show_create_table_statement.clone(),
|
||||
})?;
|
||||
Ok(row.map(|row| row.get(1)))
|
||||
}
|
||||
|
||||
@@ -598,12 +608,14 @@ impl MySqlStore {
|
||||
|
||||
match Self::parse_value_column_blob_type(&create_table_sql) {
|
||||
Some(ValueBlobType::Blob) => {
|
||||
sqlx::query(&sql_template_set.alter_value_column_statement)
|
||||
.execute(pool)
|
||||
.await
|
||||
.with_context(|_| MySqlExecutionSnafu {
|
||||
sql: sql_template_set.alter_value_column_statement.clone(),
|
||||
})?;
|
||||
sqlx::query(AssertSqlSafe(
|
||||
sql_template_set.alter_value_column_statement.as_str(),
|
||||
))
|
||||
.execute(pool)
|
||||
.await
|
||||
.with_context(|_| MySqlExecutionSnafu {
|
||||
sql: sql_template_set.alter_value_column_statement.clone(),
|
||||
})?;
|
||||
info!("Upgraded MySQL metadata value column to MEDIUMBLOB for `{table_name}`");
|
||||
}
|
||||
Some(ValueBlobType::MediumBlob | ValueBlobType::LongBlob) => {
|
||||
@@ -638,12 +650,14 @@ impl MySqlStore {
|
||||
// We check if greptime_metakv table exists, and we will create a new table
|
||||
// if it does not exist.
|
||||
let sql_template_set = MySqlTemplateFactory::new(table_name).build();
|
||||
sqlx::query(&sql_template_set.create_table_statement)
|
||||
.execute(&pool)
|
||||
.await
|
||||
.with_context(|_| MySqlExecutionSnafu {
|
||||
sql: sql_template_set.create_table_statement.clone(),
|
||||
})?;
|
||||
sqlx::query(AssertSqlSafe(
|
||||
sql_template_set.create_table_statement.as_str(),
|
||||
))
|
||||
.execute(&pool)
|
||||
.await
|
||||
.with_context(|_| MySqlExecutionSnafu {
|
||||
sql: sql_template_set.create_table_statement.clone(),
|
||||
})?;
|
||||
Self::maybe_upgrade_value_column_to_mediumblob(&pool, &sql_template_set).await?;
|
||||
Ok(Arc::new(MySqlStore {
|
||||
max_txn_ops,
|
||||
@@ -695,7 +709,10 @@ mod tests {
|
||||
|
||||
async fn show_create_table(pool: &MySqlPool, table_name: &str) -> String {
|
||||
let sql = format!("SHOW CREATE TABLE `{table_name}`");
|
||||
let row = sqlx::query(&sql).fetch_one(pool).await.unwrap();
|
||||
let row = sqlx::query(AssertSqlSafe(sql.as_str()))
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.unwrap();
|
||||
row.get::<String, _>(1)
|
||||
}
|
||||
|
||||
@@ -703,18 +720,24 @@ mod tests {
|
||||
let sql = format!(
|
||||
"CREATE TABLE IF NOT EXISTS `{table_name}`(k VARBINARY(3072) PRIMARY KEY, v BLOB);"
|
||||
);
|
||||
sqlx::query(&sql).execute(pool).await.unwrap();
|
||||
sqlx::query(AssertSqlSafe(sql.as_str()))
|
||||
.execute(pool)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
async fn drop_table(pool: &MySqlPool, table_name: &str) {
|
||||
let sql = format!("DROP TABLE IF EXISTS `{table_name}`;");
|
||||
sqlx::query(&sql).execute(pool).await.unwrap();
|
||||
sqlx::query(AssertSqlSafe(sql.as_str()))
|
||||
.execute(pool)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
async fn build_mysql_kv_backend(table_name: &str) -> Option<MySqlStore> {
|
||||
let pool = mysql_pool().await?;
|
||||
let sql_templates = MySqlTemplateFactory::new(table_name).build();
|
||||
sqlx::query(&sql_templates.create_table_statement)
|
||||
sqlx::query(AssertSqlSafe(sql_templates.create_table_statement.as_str()))
|
||||
.execute(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -67,6 +67,7 @@ servers.workspace = true
|
||||
snafu.workspace = true
|
||||
sqlx = { workspace = true, features = [
|
||||
"mysql",
|
||||
"mysql-rsa",
|
||||
"chrono",
|
||||
], optional = true }
|
||||
store-api.workspace = true
|
||||
|
||||
@@ -59,6 +59,7 @@ sql = { workspace = true }
|
||||
sqlparser.workspace = true
|
||||
sqlx = { workspace = true, features = [
|
||||
"mysql",
|
||||
"mysql-rsa",
|
||||
"chrono",
|
||||
] }
|
||||
store-api = { workspace = true }
|
||||
|
||||
@@ -110,7 +110,7 @@ pub const GT_FUZZ_CLUSTER_NAME: &str = "GT_FUZZ_CLUSTER_NAME";
|
||||
/// Flushes memtable to SST file.
|
||||
pub async fn flush_memtable(e: &Pool<MySql>, table_name: &Ident) -> Result<()> {
|
||||
let sql = format!("admin flush_table(\"{}\")", table_name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(e)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
@@ -122,7 +122,7 @@ pub async fn flush_memtable(e: &Pool<MySql>, table_name: &Ident) -> Result<()> {
|
||||
/// Triggers a compaction for table
|
||||
pub async fn compact_table(e: &Pool<MySql>, table_name: &Ident) -> Result<()> {
|
||||
let sql = format!("admin compact_table(\"{}\")", table_name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(e)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -37,7 +37,7 @@ pub async fn migrate_region(
|
||||
) -> String {
|
||||
let sql =
|
||||
format!("admin migrate_region({region_id}, {from_peer_id}, {to_peer_id}, {timeout_secs});");
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.fetch_one(e)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })
|
||||
|
||||
@@ -24,7 +24,7 @@ use crate::error;
|
||||
/// Fetches the state of a procedure.
|
||||
pub async fn procedure_state(e: &Pool<MySql>, procedure_id: &str) -> String {
|
||||
let sql = format!("admin procedure_state(\"{procedure_id}\");");
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.fetch_one(e)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })
|
||||
|
||||
@@ -221,7 +221,7 @@ pub async fn valid_marker_value(
|
||||
let sql = format!("SELECT * FROM {table_name}");
|
||||
// cache is useless and buggy anyway since alter happens all the time
|
||||
// TODO(discord9): invalid prepared sql after alter
|
||||
let res = sqlx::query(&sql)
|
||||
let res = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.persistent(false)
|
||||
.fetch_all(db)
|
||||
.await
|
||||
|
||||
@@ -155,14 +155,16 @@ pub struct ValueCount {
|
||||
}
|
||||
|
||||
pub async fn count_values(db: &MySqlPool, sql: &str) -> Result<ValueCount> {
|
||||
sqlx::query_as::<_, ValueCount>(sql)
|
||||
// Safety: the SQL is built by fuzz validators from generated identifiers only.
|
||||
sqlx::query_as::<_, ValueCount>(sqlx::AssertSqlSafe(sql))
|
||||
.fetch_one(db)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })
|
||||
}
|
||||
|
||||
pub async fn count_values_all(db: &MySqlPool, sql: &str) -> Result<Vec<ValueCount>> {
|
||||
sqlx::query_as::<_, ValueCount>(sql)
|
||||
// Safety: the SQL is built by fuzz validators from generated identifiers only.
|
||||
sqlx::query_as::<_, ValueCount>(sqlx::AssertSqlSafe(sql))
|
||||
.fetch_all(db)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })
|
||||
@@ -170,7 +172,8 @@ pub async fn count_values_all(db: &MySqlPool, sql: &str) -> Result<Vec<ValueCoun
|
||||
|
||||
/// Returns all [RowEntry] of the `table_name`.
|
||||
pub async fn fetch_values(db: &MySqlPool, sql: &str) -> Result<Vec<MySqlRow>> {
|
||||
sqlx::query(sql)
|
||||
// Safety: the SQL is built by fuzz validators from generated identifiers only.
|
||||
sqlx::query(sqlx::AssertSqlSafe(sql))
|
||||
.fetch_all(db)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })
|
||||
|
||||
@@ -47,7 +47,8 @@ fn parse_show_create(show_create: &str) -> Result<Vec<AlterTableOption>> {
|
||||
|
||||
/// Fetches table options from the context
|
||||
pub async fn fetch_table_options(db: &MySqlPool, sql: &str) -> Result<Vec<AlterTableOption>> {
|
||||
let fetched_rows = sqlx::query(sql)
|
||||
// Safety: the SQL is built by fuzz validators from generated identifiers only.
|
||||
let fetched_rows = sqlx::query(sqlx::AssertSqlSafe(sql))
|
||||
.fetch_all(db)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -123,7 +123,7 @@ async fn execute_alter_table(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
let create_physical_table_expr = generate_create_physical_table_expr(&mut rng).unwrap();
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(&create_physical_table_expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -154,7 +154,7 @@ async fn execute_alter_table(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
let create_logical_table_expr =
|
||||
generate_create_logical_table_expr(physical_table_ctx, &mut rng).unwrap();
|
||||
let sql = translator.translate(&create_logical_table_expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -178,7 +178,7 @@ async fn execute_alter_table(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
.unwrap();
|
||||
let translator = AlterTableExprTranslator;
|
||||
let sql = translator.translate(&expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -213,7 +213,7 @@ async fn execute_alter_table(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
|
||||
// Clean up logical table
|
||||
let sql = format!("DROP TABLE {}", create_logical_table_expr.table_name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -224,7 +224,7 @@ async fn execute_alter_table(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
|
||||
// Clean up physical table
|
||||
let sql = format!("DROP TABLE {}", create_physical_table_expr.table_name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -229,14 +229,14 @@ async fn execute_alter_table(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
let expr = generate_create_table_expr(&mut rng).unwrap();
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(&expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
info!("Create table: {sql}, result: {result:?}");
|
||||
|
||||
let insert = generate_insert_table_sql(&mut rng, &expr)?;
|
||||
let result = sqlx::query(&insert)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(insert.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &insert })?;
|
||||
@@ -248,7 +248,7 @@ async fn execute_alter_table(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
let expr = generate_alter_table_expr(table_ctx.clone(), &mut rng).unwrap();
|
||||
let translator = AlterTableExprTranslator;
|
||||
let sql = translator.translate(&expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -303,7 +303,7 @@ async fn execute_alter_table(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
|
||||
// select from table to make sure the table is still ok
|
||||
let sql = format!("SELECT * FROM {}", table_ctx.name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.persistent(false)
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
@@ -314,7 +314,7 @@ async fn execute_alter_table(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
// Cleans up
|
||||
let table_name = table_ctx.name.clone();
|
||||
let sql = format!("DROP TABLE {}", table_name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -74,7 +74,7 @@ async fn execute_create_database(ctx: FuzzContext, input: FuzzInput) -> Result<(
|
||||
let expr = generate_expr(input)?;
|
||||
let translator = CreateDatabaseExprTranslator;
|
||||
let sql = translator.translate(&expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -82,7 +82,7 @@ async fn execute_create_database(ctx: FuzzContext, input: FuzzInput) -> Result<(
|
||||
|
||||
// Cleans up
|
||||
let sql = format!("DROP DATABASE {}", expr.database_name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -85,7 +85,7 @@ async fn execute_create_logic_table(ctx: FuzzContext, input: FuzzInput) -> Resul
|
||||
.generate(&mut rng)?;
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(&create_physical_table_expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -128,7 +128,7 @@ async fn execute_create_logic_table(ctx: FuzzContext, input: FuzzInput) -> Resul
|
||||
.unwrap()
|
||||
.generate(&mut rng)?;
|
||||
let sql = translator.translate(&create_logical_table_expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -162,7 +162,7 @@ async fn execute_create_logic_table(ctx: FuzzContext, input: FuzzInput) -> Resul
|
||||
|
||||
// Clean up logical table
|
||||
let sql = format!("DROP TABLE {}", create_logical_table_expr.table_name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -173,7 +173,7 @@ async fn execute_create_logic_table(ctx: FuzzContext, input: FuzzInput) -> Resul
|
||||
|
||||
// Clean up physical table
|
||||
let sql = format!("DROP TABLE {}", create_physical_table_expr.table_name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -93,7 +93,7 @@ async fn execute_create_table(ctx: FuzzContext, input: FuzzInput) -> Result<()>
|
||||
let expr = generate_expr(input)?;
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(&expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -110,7 +110,7 @@ async fn execute_create_table(ctx: FuzzContext, input: FuzzInput) -> Result<()>
|
||||
|
||||
// Cleans up
|
||||
let sql = format!("DROP TABLE {}", expr.table_name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -152,7 +152,7 @@ async fn create_metric_tables<R: Rng + 'static>(
|
||||
let create_physical_expr = generate_create_physical_table_expr(partitions, rng)?;
|
||||
let translator = CreateTableExprTranslator;
|
||||
let create_physical_sql = translator.translate(&create_physical_expr)?;
|
||||
let result = sqlx::query(&create_physical_sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(create_physical_sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu {
|
||||
@@ -180,7 +180,7 @@ async fn create_metric_tables<R: Rng + 'static>(
|
||||
}
|
||||
|
||||
let create_logical_sql = translator.translate(&create_logical_expr)?;
|
||||
let result = sqlx::query(&create_logical_sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(create_logical_sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu {
|
||||
@@ -212,7 +212,7 @@ async fn execute_insert_with_retry(ctx: &FuzzContext, sql: &str) -> Result<()> {
|
||||
let mut attempt = 0;
|
||||
let max_attempts = 10;
|
||||
loop {
|
||||
match sqlx::query(sql)
|
||||
match sqlx::query(sqlx::AssertSqlSafe(sql))
|
||||
.persistent(false)
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
@@ -408,7 +408,7 @@ async fn cleanup_tables(
|
||||
) -> Result<()> {
|
||||
for table_ctx in logical_tables.values() {
|
||||
let drop_logical_sql = format!("DROP TABLE {}", table_ctx.name);
|
||||
let result = sqlx::query(&drop_logical_sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(drop_logical_sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu {
|
||||
@@ -418,7 +418,7 @@ async fn cleanup_tables(
|
||||
}
|
||||
|
||||
let drop_physical_sql = format!("DROP TABLE {}", physical_table_ctx.name);
|
||||
let result = sqlx::query(&drop_physical_sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(drop_physical_sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu {
|
||||
@@ -572,7 +572,7 @@ async fn execute_repartition_metric_table(ctx: FuzzContext, input: FuzzInput) ->
|
||||
info!("Repartition sql: {sql}");
|
||||
let started_at_ms = current_time_millis();
|
||||
let now = Instant::now();
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
|
||||
@@ -187,7 +187,7 @@ async fn execute_insert_with_retry(ctx: &FuzzContext, sql: &str) -> Result<()> {
|
||||
match ctx
|
||||
.greptime
|
||||
// unprepared query, see <https://github.com/GreptimeTeam/greptimedb/issues/3500>
|
||||
.execute(sql)
|
||||
.execute(sqlx::AssertSqlSafe(sql))
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
@@ -250,7 +250,7 @@ async fn execute_repartition_table(ctx: FuzzContext, input: FuzzInput) -> Result
|
||||
let expr = generate_create_expr(&input, &mut rng).unwrap();
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(&expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -271,7 +271,7 @@ async fn execute_repartition_table(ctx: FuzzContext, input: FuzzInput) -> Result
|
||||
let translator = RepartitionExprTranslator;
|
||||
let sql = translator.translate(&expr)?;
|
||||
info!("Initial partition sql: {sql}");
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -306,7 +306,7 @@ async fn execute_repartition_table(ctx: FuzzContext, input: FuzzInput) -> Result
|
||||
let translator = RepartitionExprTranslator;
|
||||
let sql = translator.translate(&expr)?;
|
||||
info!("Repartition sql: {sql}");
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -378,7 +378,7 @@ async fn execute_repartition_table(ctx: FuzzContext, input: FuzzInput) -> Result
|
||||
// Cleans up
|
||||
let table_name = table_ctx.name.clone();
|
||||
let sql = format!("DROP TABLE {}", table_name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -184,7 +184,7 @@ async fn execute_insert_with_retry(ctx: &FuzzContext, sql: &str) -> Result<()> {
|
||||
let mut attempt = 0;
|
||||
let max_attempts = 10;
|
||||
loop {
|
||||
match ctx.greptime.execute(sql).await {
|
||||
match ctx.greptime.execute(sqlx::AssertSqlSafe(sql)).await {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(err) => {
|
||||
tokio::time::sleep(delay).await;
|
||||
@@ -201,7 +201,7 @@ async fn execute_insert_with_retry(ctx: &FuzzContext, sql: &str) -> Result<()> {
|
||||
async fn create_table(ctx: &FuzzContext, expr: &CreateTableExpr) -> Result<TableContextRef> {
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -333,7 +333,7 @@ fn alter_table_partitions_expr_from_table_ctx<R: Rng + 'static>(
|
||||
async fn submit_repartition_procedure(ctx: &FuzzContext, expr: &RepartitionExpr) -> Result<String> {
|
||||
let translator = RepartitionExprTranslator;
|
||||
let sql = translator.translate(expr)?;
|
||||
let (procedure_id,) = sqlx::query_as::<_, (String,)>(&sql)
|
||||
let (procedure_id,) = sqlx::query_as::<_, (String,)>(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.fetch_one(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -418,7 +418,7 @@ async fn validate_terminal_metadata(
|
||||
|
||||
async fn drop_table(ctx: &FuzzContext, table_name: &tests_fuzz::ir::Ident) -> Result<()> {
|
||||
let sql = format!("DROP TABLE {}", table_name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
|
||||
@@ -110,7 +110,7 @@ async fn create_physical_table<R: Rng + 'static>(
|
||||
let create_physical_table_expr = generate_create_physical_table_expr(rng).unwrap();
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(&create_physical_table_expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -167,7 +167,7 @@ async fn insert_values<R: Rng + 'static>(
|
||||
let result = ctx
|
||||
.greptime
|
||||
// unprepared query, see <https://github.com/GreptimeTeam/greptimedb/issues/3500>
|
||||
.execute(sql.as_str())
|
||||
.execute(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
|
||||
@@ -201,7 +201,7 @@ async fn execute_failover(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
continue;
|
||||
}
|
||||
let sql = translator.translate(&create_logical_table_expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -272,7 +272,7 @@ async fn execute_failover(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
// Clean up
|
||||
for (table_ctx, _) in tables.values() {
|
||||
let sql = format!("DROP TABLE {}", table_ctx.name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
@@ -280,7 +280,7 @@ async fn execute_failover(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
}
|
||||
|
||||
let sql = format!("DROP TABLE {}", physical_table_ctx.name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -158,7 +158,7 @@ async fn execute_create_exprs(
|
||||
let _permit = semaphore.acquire().await.unwrap();
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(expr).unwrap();
|
||||
sqlx::query(&sql)
|
||||
sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })
|
||||
@@ -225,7 +225,7 @@ async fn execute_insert_exprs<R: Rng + 'static>(
|
||||
let sql = translator.translate(&insert_expr)?;
|
||||
let result = greptime
|
||||
// unprepared query, see <https://github.com/GreptimeTeam/greptimedb/issues/3500>
|
||||
.execute(sql.as_str())
|
||||
.execute(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
ensure!(
|
||||
@@ -337,7 +337,7 @@ async fn execute_failover(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
|
||||
for table_ctx in table_ctxs {
|
||||
let sql = format!("DROP TABLE {}", table_ctx.name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -130,7 +130,7 @@ async fn execute_insert(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
let create_expr = generate_create_expr(input, &mut rng)?;
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(&create_expr)?;
|
||||
let _result = sqlx::query(&sql)
|
||||
let _result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -142,7 +142,7 @@ async fn execute_insert(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
let result = ctx
|
||||
.greptime
|
||||
// unprepared query, see <https://github.com/GreptimeTeam/greptimedb/issues/3500>
|
||||
.execute(sql.as_str())
|
||||
.execute(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
|
||||
@@ -202,7 +202,7 @@ async fn execute_insert(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
|
||||
// Cleans up
|
||||
let sql = format!("DROP TABLE {}", create_expr.table_name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -141,7 +141,7 @@ async fn create_physical_table<R: Rng + 'static>(
|
||||
let create_physical_table_expr = generate_create_physical_table_expr(rng).unwrap();
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(&create_physical_table_expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -211,7 +211,7 @@ async fn insert_values<R: Rng + 'static>(
|
||||
let result = ctx
|
||||
.greptime
|
||||
// unprepared query, see <https://github.com/GreptimeTeam/greptimedb/issues/3500>
|
||||
.execute(sql.as_str())
|
||||
.execute(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
|
||||
@@ -248,7 +248,7 @@ async fn execute_insert(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
continue;
|
||||
}
|
||||
let sql = translator.translate(&create_logical_table_expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -272,7 +272,7 @@ async fn execute_insert(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
// Clean up logical table
|
||||
for (table_name, _) in tables {
|
||||
let sql = format!("DROP TABLE {}", table_name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -281,7 +281,7 @@ async fn execute_insert(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
|
||||
// Clean up physical table
|
||||
let sql = format!("DROP TABLE {}", physical_table_ctx.name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -109,7 +109,7 @@ async fn create_physical_table<R: Rng + 'static>(
|
||||
let create_physical_table_expr = generate_create_physical_table_expr(rng).unwrap();
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(&create_physical_table_expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -166,7 +166,7 @@ async fn insert_values<R: Rng + 'static>(
|
||||
let result = ctx
|
||||
.greptime
|
||||
// unprepared query, see <https://github.com/GreptimeTeam/greptimedb/issues/3500>
|
||||
.execute(sql.as_str())
|
||||
.execute(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
|
||||
@@ -208,7 +208,7 @@ async fn create_logical_table_and_insert_values(
|
||||
continue;
|
||||
}
|
||||
let sql = translator.translate(&create_logical_table_expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -406,7 +406,7 @@ async fn execute_migration(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
// Clean up
|
||||
for (table_ctx, _) in tables.values() {
|
||||
let sql = format!("DROP TABLE {}", table_ctx.name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
@@ -414,7 +414,7 @@ async fn execute_migration(ctx: FuzzContext, input: FuzzInput) -> Result<()> {
|
||||
}
|
||||
|
||||
let sql = format!("DROP TABLE {}", physical_table_ctx.name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -158,7 +158,7 @@ async fn insert_values<R: Rng + 'static>(
|
||||
let result = ctx
|
||||
.greptime
|
||||
// unprepared query, see <https://github.com/GreptimeTeam/greptimedb/issues/3500>
|
||||
.execute(sql.as_str())
|
||||
.execute(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
ensure!(
|
||||
@@ -208,7 +208,11 @@ async fn validate_insert_exprs(
|
||||
primary_keys_column_list
|
||||
);
|
||||
info!("Executing sql: {select_sql}");
|
||||
let fetched_rows = ctx.greptime.fetch_all(select_sql.as_str()).await.unwrap();
|
||||
let fetched_rows = ctx
|
||||
.greptime
|
||||
.fetch_all(sqlx::AssertSqlSafe(select_sql.as_str()))
|
||||
.await
|
||||
.unwrap();
|
||||
let mut expected_rows = replace_default(&insert_expr.values_list, table_ctx, insert_expr);
|
||||
sort_by_primary_keys(&mut expected_rows, primary_keys_idx);
|
||||
validator::row::assert_eq::<MySql>(&insert_expr.columns, &fetched_rows, &expected_rows)?;
|
||||
@@ -224,7 +228,11 @@ async fn validate_insert_exprs(
|
||||
column_list, table_ctx.name, ts_column.name, ts_value, primary_keys_column_list
|
||||
);
|
||||
info!("Executing sql: {select_sql}");
|
||||
let fetched_rows = ctx.greptime.fetch_all(select_sql.as_str()).await.unwrap();
|
||||
let fetched_rows = ctx
|
||||
.greptime
|
||||
.fetch_all(sqlx::AssertSqlSafe(select_sql.as_str()))
|
||||
.await
|
||||
.unwrap();
|
||||
let mut expected_rows = replace_default(&insert_expr.values_list, table_ctx, insert_expr);
|
||||
sort_by_primary_keys(&mut expected_rows, primary_keys_idx);
|
||||
validator::row::assert_eq::<MySql>(&insert_expr.columns, &fetched_rows, &expected_rows)?;
|
||||
@@ -291,7 +299,7 @@ async fn execute_region_migration(ctx: FuzzContext, input: FuzzInput) -> Result<
|
||||
let create_expr = generate_create_expr(input, &mut rng)?;
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(&create_expr)?;
|
||||
let _result = sqlx::query(&sql)
|
||||
let _result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -364,7 +372,7 @@ async fn execute_region_migration(ctx: FuzzContext, input: FuzzInput) -> Result<
|
||||
|
||||
// Cleans up
|
||||
let sql = format!("DROP TABLE {}", table_ctx.name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -125,7 +125,10 @@ async fn execute_unstable_create_table(
|
||||
let mysql_public = connect_mysql(DEFAULT_MYSQL_URL, "public").await;
|
||||
loop {
|
||||
let sql = format!("CREATE DATABASE IF NOT EXISTS {FUZZ_TESTS_DATABASE}");
|
||||
match sqlx::query(&sql).execute(&mysql_public).await {
|
||||
match sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&mysql_public)
|
||||
.await
|
||||
{
|
||||
Ok(result) => {
|
||||
info!("Create database: {}, result: {result:?}", sql);
|
||||
break;
|
||||
@@ -150,7 +153,9 @@ async fn execute_unstable_create_table(
|
||||
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(&expr).unwrap();
|
||||
let result = sqlx::query(&sql).execute(&ctx.greptime).await;
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await;
|
||||
match result {
|
||||
Ok(result) => {
|
||||
let state = *rx.borrow();
|
||||
@@ -179,7 +184,10 @@ async fn execute_unstable_create_table(
|
||||
|
||||
loop {
|
||||
let sql = format!("DROP DATABASE IF EXISTS {FUZZ_TESTS_DATABASE}");
|
||||
match sqlx::query(&sql).execute(&mysql_public).await {
|
||||
match sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&mysql_public)
|
||||
.await
|
||||
{
|
||||
Ok(result) => {
|
||||
info!("Drop database: {}, result: {result:?}", sql);
|
||||
break;
|
||||
|
||||
@@ -255,7 +255,7 @@ async fn create_tables<R: Rng + 'static>(
|
||||
let create_expr = generate_create_expr(input, idx, rng)?;
|
||||
let translator = CreateTableExprTranslator;
|
||||
let sql = translator.translate(&create_expr)?;
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
@@ -288,7 +288,7 @@ async fn insert_table<R: Rng + 'static>(
|
||||
let result = ctx
|
||||
.greptime
|
||||
// unprepared query, see <https://github.com/GreptimeTeam/greptimedb/issues/3500>
|
||||
.execute(sql.as_str())
|
||||
.execute(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql: &sql })?;
|
||||
ensure!(
|
||||
@@ -350,7 +350,11 @@ async fn validate_insert_exprs(
|
||||
primary_keys_column_list
|
||||
);
|
||||
info!("Executing sql: {select_sql}");
|
||||
let fetched_rows = ctx.greptime.fetch_all(select_sql.as_str()).await.unwrap();
|
||||
let fetched_rows = ctx
|
||||
.greptime
|
||||
.fetch_all(sqlx::AssertSqlSafe(select_sql.as_str()))
|
||||
.await
|
||||
.unwrap();
|
||||
let mut expected_rows = replace_default(&insert_expr.values_list, table_ctx, insert_expr);
|
||||
sort_by_primary_keys(&mut expected_rows, primary_keys_idx);
|
||||
validator::row::assert_eq::<MySql>(&insert_expr.columns, &fetched_rows, &expected_rows)?;
|
||||
@@ -367,7 +371,11 @@ async fn validate_insert_exprs(
|
||||
column_list, table_ctx.name, ts_column.name, ts_value, primary_keys_column_list
|
||||
);
|
||||
info!("Executing sql: {select_sql}");
|
||||
let fetched_rows = ctx.greptime.fetch_all(select_sql.as_str()).await.unwrap();
|
||||
let fetched_rows = ctx
|
||||
.greptime
|
||||
.fetch_all(sqlx::AssertSqlSafe(select_sql.as_str()))
|
||||
.await
|
||||
.unwrap();
|
||||
let mut expected_rows = replace_default(&insert_expr.values_list, table_ctx, insert_expr);
|
||||
sort_by_primary_keys(&mut expected_rows, primary_keys_idx);
|
||||
validator::row::assert_eq::<MySql>(&insert_expr.columns, &fetched_rows, &expected_rows)?;
|
||||
@@ -620,7 +628,7 @@ async fn execute_logical_prune_fuzz<W: WalAdmin>(
|
||||
|
||||
for table in tables {
|
||||
let sql = format!("DROP TABLE {}", table.ctx.name);
|
||||
let result = sqlx::query(&sql)
|
||||
let result = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.execute(&ctx.greptime)
|
||||
.await
|
||||
.context(error::ExecuteQuerySnafu { sql })?;
|
||||
|
||||
@@ -119,6 +119,7 @@ servers = { workspace = true, features = ["testing"] }
|
||||
similar-asserts.workspace = true
|
||||
sqlx = { workspace = true, features = [
|
||||
"mysql",
|
||||
"mysql-rsa",
|
||||
"postgres",
|
||||
"chrono",
|
||||
] }
|
||||
|
||||
@@ -220,7 +220,10 @@ async fn test_json2_multi_row_insert() {
|
||||
i,
|
||||
json
|
||||
);
|
||||
conn.execute(sql.as_str()).await.unwrap();
|
||||
// Safety: the SQL is built from test-local identifiers and payloads only.
|
||||
conn.execute(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
@@ -237,9 +240,8 @@ async fn create_json2_table(
|
||||
table_name: &str,
|
||||
merge_threshold: usize,
|
||||
) -> sqlx::Result<()> {
|
||||
conn.execute(
|
||||
format!(
|
||||
r#"
|
||||
let sql = format!(
|
||||
r#"
|
||||
CREATE TABLE {table_name} (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
host STRING PRIMARY KEY,
|
||||
@@ -252,10 +254,9 @@ CREATE TABLE {table_name} (
|
||||
'memtable.bulk.encode_row_threshold' = '1000000'
|
||||
)
|
||||
"#
|
||||
)
|
||||
.as_str(),
|
||||
)
|
||||
.await?;
|
||||
);
|
||||
// Safety: the SQL is built from test-local identifiers only.
|
||||
conn.execute(sqlx::AssertSqlSafe(sql.as_str())).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -263,9 +264,8 @@ async fn create_json2_compaction_table(
|
||||
conn: &mut MySqlConnection,
|
||||
table_name: &str,
|
||||
) -> sqlx::Result<()> {
|
||||
conn.execute(
|
||||
format!(
|
||||
r#"
|
||||
let sql = format!(
|
||||
r#"
|
||||
CREATE TABLE {table_name} (
|
||||
ts TIMESTAMP TIME INDEX,
|
||||
host STRING PRIMARY KEY,
|
||||
@@ -279,17 +279,15 @@ CREATE TABLE {table_name} (
|
||||
'memtable.bulk.encode_bytes_threshold' = '100000000'
|
||||
)
|
||||
"#
|
||||
)
|
||||
.as_str(),
|
||||
)
|
||||
.await?;
|
||||
);
|
||||
// Safety: the SQL is built from test-local identifiers only.
|
||||
conn.execute(sqlx::AssertSqlSafe(sql.as_str())).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn query_json2_rows(conn: &mut MySqlConnection, table_name: &str) -> sqlx::Result<Json2Rows> {
|
||||
let rows = sqlx::query(
|
||||
format!(
|
||||
r#"
|
||||
let sql = format!(
|
||||
r#"
|
||||
SELECT
|
||||
host,
|
||||
j.payload.id::STRING AS payload_id,
|
||||
@@ -299,11 +297,11 @@ SELECT
|
||||
FROM {table_name}
|
||||
ORDER BY ts
|
||||
"#
|
||||
)
|
||||
.as_str(),
|
||||
)
|
||||
.fetch_all(conn)
|
||||
.await?;
|
||||
);
|
||||
// Safety: the SQL is built from test-local identifiers only.
|
||||
let rows = sqlx::query(sqlx::AssertSqlSafe(sql.as_str()))
|
||||
.fetch_all(conn)
|
||||
.await?;
|
||||
|
||||
Ok(rows
|
||||
.into_iter()
|
||||
@@ -320,9 +318,12 @@ ORDER BY ts
|
||||
}
|
||||
|
||||
async fn count_table_rows(conn: &mut MySqlConnection, table_name: &str) -> sqlx::Result<i64> {
|
||||
let row = sqlx::query(format!("SELECT COUNT(*) AS count FROM {table_name}").as_str())
|
||||
.fetch_one(conn)
|
||||
.await?;
|
||||
// Safety: the SQL is built from test-local identifiers only.
|
||||
let row = sqlx::query(sqlx::AssertSqlSafe(
|
||||
format!("SELECT COUNT(*) AS count FROM {table_name}").as_str(),
|
||||
))
|
||||
.fetch_one(conn)
|
||||
.await?;
|
||||
Ok(row.get("count"))
|
||||
}
|
||||
|
||||
|
||||
@@ -198,7 +198,8 @@ pub async fn test_mysql_auth(store_type: StorageType) {
|
||||
"test",
|
||||
"writeonly_user",
|
||||
|query| async move {
|
||||
sqlx::query_scalar::<_, bool>(&query)
|
||||
// Safety: the SQL is built from test-local identifiers only.
|
||||
sqlx::query_scalar::<_, bool>(sqlx::AssertSqlSafe(query.as_str()))
|
||||
.fetch_one(actor_query_pool)
|
||||
.await
|
||||
.unwrap_or(false)
|
||||
@@ -563,7 +564,8 @@ pub async fn test_postgres_auth(store_type: StorageType) {
|
||||
"postgres_auth_actor",
|
||||
"writeonly_user",
|
||||
|query| async move {
|
||||
sqlx::query_scalar::<_, bool>(&query)
|
||||
// Safety: the SQL is built from test-local identifiers only.
|
||||
sqlx::query_scalar::<_, bool>(sqlx::AssertSqlSafe(query.as_str()))
|
||||
.fetch_one(actor_query_pool)
|
||||
.await
|
||||
.unwrap_or(false)
|
||||
@@ -784,7 +786,8 @@ pub async fn test_mysql_slow_query(store_type: StorageType) {
|
||||
|
||||
let row = tokio::time::timeout(Duration::from_secs(10), async {
|
||||
loop {
|
||||
if let Ok(Some(row)) = sqlx::query(&query)
|
||||
// Safety: the SQL is built from test-local identifiers only.
|
||||
if let Ok(Some(row)) = sqlx::query(sqlx::AssertSqlSafe(query.as_str()))
|
||||
.bind(slow_query)
|
||||
.fetch_optional(&pool)
|
||||
.await
|
||||
@@ -1142,7 +1145,8 @@ pub async fn test_postgres_slow_query(store_type: StorageType) {
|
||||
|
||||
let row = tokio::time::timeout(Duration::from_secs(10), async {
|
||||
loop {
|
||||
if let Ok(Some(row)) = sqlx::query(&query)
|
||||
// Safety: the SQL is built from test-local identifiers only.
|
||||
if let Ok(Some(row)) = sqlx::query(sqlx::AssertSqlSafe(query.as_str()))
|
||||
.bind(slow_query)
|
||||
.fetch_optional(&pool)
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user