久保様
趣味でrustをいじり始めたのですがdbfluteの無い世界は住み難いので、
dbfluteを活用したので報告します。
テーブルや テーブルをJOINしたentityはまずJAVAでdbfluteのBsEntityをもとにAccessでrustのstructを自動作成しました。
またInsertやUpdateもそのstructを活用して自動作成しました。
Updateは通常 entityを読み込んで一部更新が必要なものを変更してコミットするのでうまく行きそうです。
またSelectはまず全項目をentityから自動作成して、それをもとにTwo Way Sqlファイルを作成し、dbfぅてdbfluteでpmberanを作りそれをもとにrustのstructのpmbeanを自動作成しています。
rustは初めての言語ですのでMicrosoft Copilotの世話になりっぱなしです。
疑問点やエラーを送ると即座に修正したプログラムを書いてくれます。
今回Two Way SQL とPmbeanから動的にSQLを作成するプログラムをCopulotに要件提示し、何度かテストしながら修正して動く様になりました。
Copilotさまさまです。またGithub Copilotもすごく良い提案をしてくれます。
Two Way SQLまで補完してくれたのには驚きました。
参考までCopiltが作った 動的SQL作成プログラムをつけます。
ub async fn process_sql<P>(params: &P, filename: &str) -> io::Result<String>
where
P: Serialize,
{
let mut file = File::open(filename)?;
let mut sql = String::new();
file.read_to_string(&mut sql)?;
// JSONにシリアライズ
let params_json = serde_json::to_value(params).unwrap();
// フィールド名と値を動的に取得
let mut replacements = HashMap::new();
if let serde_json::Value::Object(map) = params_json {
for (key, value) in map.iter() {
if value.is_null() {
replacements.insert(key.clone(), None);
} else if let serde_json::Value::String(val) = value {
replacements.insert(key.clone(), Some(format!("'{}'", val)));
} else if let serde_json::Value::Number(val) = value {
replacements.insert(key.clone(), Some(val.to_string()));
} else if key == "RegisterDatetime" {
let datetime = value.as_str().unwrap();
replacements.insert(key.clone(), Some(format!("'{}'", datetime)));
} else {
replacements.insert(key.clone(), Some(value.to_string()));
}
}
}
// プレースホルダーの置換と行の削除
for (key, value) in replacements.iter() {
let placeholder_pattern = format!(r"/\*pmb\.{}\*/[^ ,)\n]*", key);
let re = Regex::new(&placeholder_pattern).unwrap();
if let Some(val) = value {
sql = re.replace_all(&sql, val).to_string();
} else {
// プレースホルダーを含む行全体を削除し、前後のカンマを適切に処理
let line_pattern = format!(r"(?m)^\s*([^,]*,)?\s*.*{}\*/[^\n]*,?", key);
let line_re = Regex::new(&line_pattern).unwrap();
sql = line_re.replace_all(&sql, "").to_string();
}
}
// 不要なANDやWHEREを削除
sql = Regex::new(r"(?i)\s*AND\s*$").unwrap().replace_all(&sql, "").to_string();
sql = Regex::new(r"(?i)\s*WHERE\s*$").unwrap().replace_all(&sql, "").to_string();
println!("{:?}", sql);
Ok(sql)
}
pub async fn get_login(pool: &sqlx::PgPool, params: &get_login_pmb) -> Result<Vec<login>> {
let sql = process_sql(params, "resources/Getlogin.sql").await?;
let rows = sqlx::query_as::<_, login>(
sql.as_str()
)
.fetch_all(pool)
.await?;
Ok(rows)
}
pub async fn test_sql() -> String {
// 構造体を mut で宣言
let mut params = get_login_pmb {
Id: None,
LoginId: None,
};
// 構造体の値を変更
params.Id = Some(3);
params.LoginId = None;
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let pool = PgPoolOptions::new()
.max_connections(5)
.connect(&database_url) // ここを修正
.await
.expect("Failed to create pool");
let logins = get_login(&pool, ¶ms).await.unwrap();
let mut login = logins[0].clone();
println!("{:?}", login);
"ok".to_string()
}
これが自動作成で1時間も掛からずに出来るのは凄いですね。
志村