use crate::dialect::quote_string_literal;
use crate::executor::Executor;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExistingColumn {
pub name: String,
pub declared_type: String,
pub not_null: bool,
pub is_pk: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExistingIndex {
pub name: String,
pub unique: bool,
}
pub async fn existing_columns<E: Executor + Sync>(
executor: &E,
table: &str,
) -> crate::Result<Vec<ExistingColumn>> {
let mut sql = String::from(
"SELECT name, type AS col_type, \"notnull\" AS is_not_null, pk FROM pragma_table_info(",
);
quote_string_literal(table, &mut sql);
sql.push_str(") ORDER BY cid");
let rows = executor.fetch_all(sql, Vec::new()).await?;
let mut columns = Vec::with_capacity(rows.len());
for row in &rows {
let name: String = row.get("name")?;
let declared_type: String = row.get("col_type").unwrap_or_default();
let not_null: i64 = row.get("is_not_null")?;
let pk: i64 = row.get("pk")?;
columns.push(ExistingColumn {
name,
declared_type,
not_null: not_null != 0,
is_pk: pk != 0,
});
}
Ok(columns)
}
pub async fn table_exists<E: Executor + Sync>(executor: &E, table: &str) -> crate::Result<bool> {
let rows = executor
.fetch_all(
"SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1".to_string(),
vec![crate::Value::Text(table.to_string())],
)
.await?;
Ok(!rows.is_empty())
}
pub async fn existing_indexes<E: Executor + Sync>(
executor: &E,
table: &str,
) -> crate::Result<Vec<ExistingIndex>> {
let mut sql =
String::from("SELECT name AS idx_name, \"unique\" AS is_unique FROM pragma_index_list(");
quote_string_literal(table, &mut sql);
sql.push_str(") WHERE origin = 'c'");
let rows = executor.fetch_all(sql, Vec::new()).await?;
let mut indexes = Vec::with_capacity(rows.len());
for row in &rows {
let name: String = row.get("idx_name")?;
let unique: i64 = row.get("is_unique")?;
indexes.push(ExistingIndex {
name,
unique: unique != 0,
});
}
Ok(indexes)
}