Skip to content

Commit

Permalink
Merge pull request #3926 from longsleep-io/longsleep-sqlite-fix-impli…
Browse files Browse the repository at this point in the history
…cit-rowid

Add implicit sqlite rowid columns to print-schema output
  • Loading branch information
weiznich authored Feb 20, 2024
2 parents 57346fa + 8c4fa4a commit 51c02d4
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 6 deletions.
28 changes: 28 additions & 0 deletions diesel_cli/src/infer_schema_internals/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ fn get_sqlite_version(conn: &mut SqliteConnection) -> QueryResult<SqliteVersion>
Ok(SqliteVersion::new(parts[0], parts[1], parts[2]))
}

// In sqlite the rowid is a signed 64-bit integer.
// See: https://sqlite.org/rowidtable.html
// We should use BigInt here but to avoid type problems with foreign keys to
// rowid columns this is for now not done. A patch can be used after the schema
// is generated to convert the columns to BigInt as needed.
const ROWID_TYPE_NAME: &str = "Integer";

pub fn get_table_data(
conn: &mut SqliteConnection,
table: &TableName,
Expand All @@ -134,6 +141,27 @@ pub fn get_table_data(
// 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)?;
// Add implicit rowid primary key column if the only primary key is rowid
// and ensure that the rowid column uses the right type.
let primary_key = get_primary_keys(conn, table)?;
if primary_key.len() == 1 {
let primary_key = primary_key.first().expect("guaranteed to have one element");
if !result.iter_mut().any(|x| &x.column_name == primary_key) {
// Prepend implicit rowid column for the rowid implicit primary key.
result.insert(
0,
ColumnInformation {
column_name: String::from(primary_key),
type_name: String::from(ROWID_TYPE_NAME),
type_schema: None,
nullable: false,
max_length: None,
comment: None,
},
);
}
}

match column_sorting {
ColumnSorting::OrdinalPosition => {}
ColumnSorting::Name => {
Expand Down
6 changes: 6 additions & 0 deletions diesel_cli/tests/print_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,12 @@ fn print_schema_sqlite_implicit_foreign_key_reference() {
test_print_schema("print_schema_sqlite_implicit_foreign_key_reference", vec![]);
}

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

#[test]
#[cfg(feature = "postgres")]
fn print_schema_respects_type_name_case() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,85 @@ description: "Test: print_schema_sqlite_without_explicit_primary_key"
diesel::table! {
no_explicit (rowid) {
rowid -> Integer,
name -> Text,
name -> Nullable<Text>,
}
}

diesel::table! {
with_explicit_aliased_rowid (id) {
id -> Nullable<Integer>,
name -> Nullable<Text>,
}
}

diesel::table! {
with_explicit_aliased_rowid_not_null (id) {
id -> Integer,
name -> Nullable<Text>,
}
}

diesel::table! {
with_explicit_pk_rowid (rowid) {
rowid -> Nullable<Integer>,
name -> Nullable<Text>,
}
}

diesel::table! {
with_explicit_pk_rowid_autoincrement (rowid) {
rowid -> Nullable<Integer>,
name -> Nullable<Text>,
}
}

diesel::table! {
with_explicit_pk_rowid_autoincrement_not_null (rowid) {
rowid -> Integer,
name -> Nullable<Text>,
}
}

diesel::table! {
with_explicit_pk_rowid_not_null (rowid) {
rowid -> Integer,
name -> Nullable<Text>,
}
}

diesel::table! {
with_explicit_rowid (oid) {
oid -> Integer,
name -> Text,
rowid -> Text,
name -> Nullable<Text>,
rowid -> Nullable<Text>,
}
}

diesel::table! {
with_explicit_rowid_oid (_rowid_) {
_rowid_ -> Integer,
name -> Text,
rowid -> Text,
oid -> Text,
name -> Nullable<Text>,
rowid -> Nullable<Text>,
oid -> Nullable<Text>,
}
}

diesel::table! {
without_rowid (word) {
word -> Text,
cnt -> Nullable<Integer>,
}
}

diesel::allow_tables_to_appear_in_same_query!(
no_explicit,
with_explicit_aliased_rowid,
with_explicit_aliased_rowid_not_null,
with_explicit_pk_rowid,
with_explicit_pk_rowid_autoincrement,
with_explicit_pk_rowid_autoincrement_not_null,
with_explicit_pk_rowid_not_null,
with_explicit_rowid,
with_explicit_rowid_oid,
without_rowid,
);
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,38 @@ CREATE TABLE with_explicit_rowid_oid (
rowid TEXT,
oid TEXT
);

CREATE TABLE with_explicit_pk_rowid (
rowid INTEGER PRIMARY KEY,
name TEXT
);

CREATE TABLE with_explicit_pk_rowid_autoincrement (
rowid INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT
);

CREATE TABLE with_explicit_pk_rowid_not_null (
rowid INTEGER PRIMARY KEY NOT NULL,
name TEXT
);

CREATE TABLE with_explicit_pk_rowid_autoincrement_not_null (
rowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
name TEXT
);

CREATE TABLE with_explicit_aliased_rowid (
id INTEGER PRIMARY KEY,
name TEXT
);

CREATE TABLE with_explicit_aliased_rowid_not_null (
id INTEGER PRIMARY KEY NOT NULL,
name TEXT
);

CREATE TABLE without_rowid (
word TEXT PRIMARY KEY,
cnt INTEGER
) WITHOUT ROWID;

0 comments on commit 51c02d4

Please sign in to comment.