Skip to content

Commit

Permalink
Merge pull request diesel-rs#2916 from gorbit99/master
Browse files Browse the repository at this point in the history
Added generated column support for sqlite when the type is specified
  • Loading branch information
weiznich authored Jan 18, 2022
2 parents a213fe2 + 2857d03 commit bdd008c
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 5 deletions.
4 changes: 2 additions & 2 deletions diesel_cli/src/infer_schema_internals/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ where
#[cfg(feature = "sqlite")]
impl<ST> Queryable<ST, Sqlite> for ColumnInformation
where
(i32, String, String, bool, Option<String>, bool): FromStaticSqlRow<ST, Sqlite>,
(i32, String, String, bool, Option<String>, bool, i32): FromStaticSqlRow<ST, Sqlite>,
{
type Row = (i32, String, String, bool, Option<String>, bool);
type Row = (i32, String, String, bool, Option<String>, bool, i32);

fn build(row: Self::Row) -> deserialize::Result<Self> {
Ok(ColumnInformation::new(row.1, row.2, None, !row.3))
Expand Down
55 changes: 52 additions & 3 deletions diesel_cli/src/infer_schema_internals/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ table! {
notnull -> Bool,
dflt_value -> Nullable<VarChar>,
pk -> Bool,
hidden -> Integer,
}
}

Expand Down Expand Up @@ -89,12 +90,50 @@ pub fn load_foreign_key_constraints(
Ok(rows.into_iter().flatten().collect())
}

#[derive(PartialEq, Eq, PartialOrd, Ord)]
struct SqliteVersion {
major: u32,
minor: u32,
patch: u32,
}

impl SqliteVersion {
pub fn new(major: u32, minor: u32, patch: u32) -> SqliteVersion {
SqliteVersion {
major,
minor,
patch,
}
}
}

fn get_sqlite_version(conn: &mut SqliteConnection) -> SqliteVersion {
let query = "SELECT sqlite_version()";
let result = sql::<sql_types::Text>(&query).load::<String>(conn).unwrap();
let parts = result[0]
.split('.')
.map(|part| part.parse().unwrap())
.collect::<Vec<u32>>();
assert_eq!(parts.len(), 3);
SqliteVersion::new(parts[0], parts[1], parts[2])
}

pub fn get_table_data(
conn: &mut SqliteConnection,
table: &TableName,
column_sorting: &ColumnSorting,
) -> QueryResult<Vec<ColumnInformation>> {
let query = format!("PRAGMA TABLE_INFO('{}')", &table.sql_name);
let sqlite_version = get_sqlite_version(conn);
let query = if sqlite_version >= SqliteVersion::new(3, 26, 0) {
/*
* To get generated columns we need to use TABLE_XINFO
* This would return hidden columns as well, but those would need to be created at runtime
* therefore they aren't an issue.
*/
format!("PRAGMA TABLE_XINFO('{}')", &table.sql_name)
} else {
format!("PRAGMA TABLE_INFO('{}')", &table.sql_name)
};
let mut result = sql::<pragma_table_info::SqlType>(&query).load(conn)?;
match column_sorting {
ColumnSorting::OrdinalPosition => {}
Expand All @@ -115,6 +154,7 @@ struct FullTableInfo {
_not_null: bool,
_dflt_value: Option<String>,
primary_key: bool,
_hidden: i32,
}

#[derive(Queryable)]
Expand All @@ -133,7 +173,12 @@ pub fn get_primary_keys(
conn: &mut SqliteConnection,
table: &TableName,
) -> QueryResult<Vec<String>> {
let query = format!("PRAGMA TABLE_INFO('{}')", &table.sql_name);
let sqlite_version = get_sqlite_version(conn);
let query = if sqlite_version >= SqliteVersion::new(3, 26, 0) {
format!("PRAGMA TABLE_XINFO('{}')", &table.sql_name)
} else {
format!("PRAGMA TABLE_INFO('{}')", &table.sql_name)
};
let results = sql::<pragma_table_info::SqlType>(&query).load::<FullTableInfo>(conn)?;
Ok(results
.into_iter()
Expand All @@ -144,7 +189,11 @@ pub fn get_primary_keys(
pub fn determine_column_type(
attr: &ColumnInformation,
) -> Result<ColumnType, Box<dyn Error + Send + Sync + 'static>> {
let type_name = attr.type_name.to_lowercase();
let mut type_name = attr.type_name.to_lowercase();
if type_name == "generated always" {
type_name.clear();
}

let path = if is_bool(&type_name) {
String::from("Bool")
} else if is_smallint(&type_name) {
Expand Down
12 changes: 12 additions & 0 deletions diesel_cli/tests/print_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,18 @@ fn print_schema_specifying_schema_name_with_custom_type() {
)
}

#[test]
#[cfg(feature = "sqlite")]
fn print_schema_generated_columns() {
test_print_schema("print_schema_generated_columns", vec![])
}

#[test]
#[cfg(feature = "sqlite")]
fn print_schema_generated_columns_with_generated_always() {
test_print_schema("print_schema_generated_columns_generated_always", vec![])
}

#[cfg(feature = "sqlite")]
const BACKEND: &str = "sqlite";
#[cfg(feature = "postgres")]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[print_schema]
file = "src/schema.rs"
with_docs = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// @generated automatically by Diesel CLI.

diesel::table! {
generated (id) {
id -> Nullable<Integer>,
generated -> Nullable<Integer>,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CREATE TABLE generated (
id integer primary key,
generated integer as (id * 3)
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[print_schema]
file = "src/schema.rs"
with_docs = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// @generated automatically by Diesel CLI.

diesel::table! {
generated (id) {
id -> Nullable<Integer>,
generated -> Nullable<Integer>,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CREATE TABLE generated (
id integer primary key,
generated integer generated always as (id * 3)
);

0 comments on commit bdd008c

Please sign in to comment.