Repository: diesel-rs/diesel
File: diesel_cli/src/infer_schema_internals/sqlite.rs (Rust)

Code before:
            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 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)
    };

    // See: https://github.com/diesel-rs/diesel/issues/3579 as to why we use a direct
    // `sql_query` with `QueryableByName` instead of using `sql::<pragma_table_info::SqlType>`.
    let mut result = sql_query(query).load::<ColumnInformation>(conn)?;
    match column_sorting {
        ColumnSorting::OrdinalPosition => {}
        ColumnSorting::Name => {
            result.sort_by(|a: &ColumnInformation, b: &ColumnInformation| {
                a.column_name.partial_cmp(&b.column_name).unwrap()
            });
        }
    };
    Ok(result)
}

impl QueryableByName<Sqlite> for ColumnInformation {
    fn build<'a>(row: &impl NamedRow<'a, Sqlite>) -> deserialize::Result<Self> {
        let column_name =

Review comment (suggestion):
I think the `table!` definition of `pragma_table_info` can now be removed. It's not used anymore, beside in the implementation of `QueryableByName` and there we can just use the sql types from the table definition.

Code after:
        .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 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)
    };

    // See: https://github.com/diesel-rs/diesel/issues/3579 as to why we use a direct
    // `sql_query` with `QueryableByName` instead of using `sql::<pragma_table_info::SqlType>`.
    let mut result = sql_query(query).load::<ColumnInformation>(conn)?;
    match column_sorting {
        ColumnSorting::OrdinalPosition => {}
        ColumnSorting::Name => {
            result.sort_by(|a: &ColumnInformation, b: &ColumnInformation| {
                a.column_name.partial_cmp(&b.column_name).unwrap()
            });
        }
    };
    Ok(result)
}

impl QueryableByName<Sqlite> for ColumnInformation {
    fn build<'a>(row: &impl NamedRow<'a, Sqlite>) -> deserialize::Result<Self> {
        let column_name = NamedRow::get::<Text, String>(row, "name")?;
        let type_name = NamedRow::get::<Text, String>(row, "type")?;
        let notnull = NamedRow::get::<Bool, bool>(row, "notnull")?;

        Ok(Self::new(
            column_name,
            type_name,
            None,
            !notnull,
            None,
            None,
        ))