use std::env;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let host = env::var("DM_HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
let port: u16 = env::var("DM_PORT")
.unwrap_or_else(|_| "5236".to_string())
.parse()
.unwrap_or(5236);
let user = env::var("DM_USER").unwrap_or_else(|_| "SYSDBA".to_string());
let pass = env::var("DM_PASS").unwrap_or_else(|_| "SYSDBA".to_string());
let mut client = dameng::Client::new(&host, port);
client.connect(&user, &pass)?;
println!("Connected!");
println!("\n=== Preparing test data ===");
let _ = client.execute("DELETE FROM sample_item WHERE sample_id IN (1, 2, 3)");
let _ = client.execute("DELETE FROM sample_detail WHERE id IN (1, 2, 3)");
let _ = client.execute("DELETE FROM sample WHERE id IN (1, 2, 3)");
client.execute("INSERT INTO sample (ID, NAME) VALUES (1, 'Alice')")?;
client.execute("INSERT INTO sample (ID, NAME) VALUES (2, 'Bob')")?;
client.execute("INSERT INTO sample (ID, NAME) VALUES (3, 'Charlie')")?;
client.execute(
"INSERT INTO sample_detail (ID, ADDRESS, PHONE) VALUES (1, 'Beijing 123', '13800138000')",
)?;
client.execute(
"INSERT INTO sample_detail (ID, ADDRESS, PHONE) VALUES (2, 'Shanghai 456', '13900139000')",
)?;
client.execute(
"INSERT INTO sample_item (SAMPLE_ID, ITEM_ID, ITEM_NAME, BUY_TIME) VALUES (1, 101, 'Keyboard', '2024-01-15 10:30:00')",
)?;
client.execute(
"INSERT INTO sample_item (SAMPLE_ID, ITEM_ID, ITEM_NAME, BUY_TIME) VALUES (1, 102, 'Mouse', '2024-02-20 14:45:00')",
)?;
client.execute(
"INSERT INTO sample_item (SAMPLE_ID, ITEM_ID, ITEM_NAME, BUY_TIME) VALUES (2, 201, 'Monitor', '2024-03-10 09:00:00')",
)?;
println!("Data prepared.");
println!("\n=== INT type (sample.ID) ===");
let rs = client.query("SELECT ID FROM SAMPLE WHERE ID = 1")?;
println!(
" Column: {} (type_code={}, type_name={})",
rs.columns[0].name, rs.columns[0].type_code, rs.columns[0].type_name
);
for row in rs.iter() {
let id = row.get_i32(0)?;
println!(" Value: {}", id);
}
println!("\n=== VARCHAR type (sample.NAME, sample_detail.ADDRESS) ===");
let rs = client.query(
"SELECT S.NAME, SD.ADDRESS FROM SAMPLE S JOIN SAMPLE_DETAIL SD ON S.ID = SD.ID WHERE S.ID = 1",
)?;
println!(
" Columns: {:?}",
rs.columns
.iter()
.map(|c| format!("{}({},{})", c.name, c.type_code, c.type_name))
.collect::<Vec<_>>()
);
for row in rs.iter() {
let name = row.get_str(0)?;
let addr = row.get_str(1)?;
println!(" NAME={}, ADDRESS={}", name, addr);
}
println!("\n=== TIMESTAMP type (sample_item.BUY_TIME) ===");
let rs = client.query(
"SELECT ITEM_NAME, BUY_TIME FROM SAMPLE_ITEM WHERE SAMPLE_ID = 1 ORDER BY BUY_TIME",
)?;
println!(
" Columns: {:?}",
rs.columns
.iter()
.map(|c| format!("{}({},{})", c.name, c.type_code, c.type_name))
.collect::<Vec<_>>()
);
for row in rs.iter() {
let item = row.get_str(0)?;
let time = row.get_str(1)?;
println!(" ITEM_NAME={}, BUY_TIME={}", item, time);
}
println!("\n=== NULL handling (LEFT JOIN with missing detail) ===");
let rs = client.query(
"SELECT S.ID, S.NAME, SD.ADDRESS, SD.PHONE FROM SAMPLE S LEFT JOIN SAMPLE_DETAIL SD ON S.ID = SD.ID WHERE S.ID = 3",
)?;
for row in rs.iter() {
let id = row.get_i32(0)?;
let name = row.get_str(1)?;
println!(" ID={}, NAME={}", id, name);
println!(
" ADDRESS is_null={}, PHONE is_null={}",
row.is_null(2),
row.is_null(3)
);
let addr = if row.is_null(2) {
"NULL".to_string()
} else {
row.get_str(2).ok().unwrap_or_default().to_string()
};
let phone = if row.is_null(3) {
"NULL".to_string()
} else {
row.get_str(3).ok().unwrap_or_default().to_string()
};
println!(" ADDRESS={}, PHONE={}", addr, phone);
}
println!("\n=== COUNT aggregate ===");
let rs = client.query("SELECT COUNT(*) AS TOTAL FROM SAMPLE")?;
println!(
" Column: {} (type_code={}, type_name={})",
rs.columns[0].name, rs.columns[0].type_code, rs.columns[0].type_name
);
for row in rs.iter() {
let total = row.get_i32(0)?;
println!(" COUNT(*) = {}", total);
}
println!("\n=== Composite PK (sample_item: SAMPLE_ID + ITEM_ID) ===");
let rs = client.query(
"SELECT SAMPLE_ID, ITEM_ID, ITEM_NAME FROM SAMPLE_ITEM ORDER BY SAMPLE_ID, ITEM_ID",
)?;
println!(
" Columns: {:?}",
rs.columns
.iter()
.map(|c| format!("{}({})", c.name, c.type_name))
.collect::<Vec<_>>()
);
for row in rs.iter() {
let sid = row.get_i32(0)?;
let iid = row.get_i32(1)?;
let name = row.get_str(2)?;
println!(" SAMPLE_ID={}, ITEM_ID={}, ITEM_NAME={}", sid, iid, name);
}
println!("\n=== Mixed types (INT + VARCHAR + TIMESTAMP) ===");
let rs = client.query(
"SELECT SI.SAMPLE_ID, S.NAME, SI.ITEM_NAME, TO_CHAR(SI.BUY_TIME, 'YYYY-MM-DD HH24:MI:SS') AS BUY_TIME FROM SAMPLE_ITEM SI JOIN SAMPLE S ON SI.SAMPLE_ID = S.ID ORDER BY SI.SAMPLE_ID, SI.ITEM_ID",
)?;
println!(
" Columns: {:?}",
rs.columns
.iter()
.map(|c| format!("{}({},{})", c.name, c.type_code, c.type_name))
.collect::<Vec<_>>()
);
for row in rs.iter() {
let sid = row.get_i32(0)?;
let name = row.get_str(1)?;
let item = row.get_str(2)?;
let time = row.get_str(3)?;
println!(" SID={}, NAME={}, ITEM={}, TIME={}", sid, name, item, time);
}
println!("\n=== Row column count ===");
let rs = client.query(
"SELECT S.ID, S.NAME, SD.ADDRESS, SD.PHONE, SI.ITEM_NAME FROM SAMPLE S JOIN SAMPLE_DETAIL SD ON S.ID = SD.ID JOIN SAMPLE_ITEM SI ON S.ID = SI.SAMPLE_ID",
)?;
for row in rs.iter() {
println!(" Row has {} columns", row.len());
assert!(!row.is_empty());
}
println!("\n=== Column nullable metadata ===");
let rs = client.query("SELECT ID, ADDRESS, PHONE FROM SAMPLE_DETAIL")?;
for col in rs.columns.iter() {
println!(" {} : nullable={}", col.name, col.nullable);
}
println!("\n=== Cleanup ===");
let _ = client.execute("DELETE FROM sample_item WHERE sample_id IN (1, 2, 3)");
let _ = client.execute("DELETE FROM sample_detail WHERE id IN (1, 2, 3)");
let _ = client.execute("DELETE FROM sample WHERE id IN (1, 2, 3)");
client.commit()?;
println!("\nDone!");
Ok(())
}