Skip to content

Commit

Permalink
Merge pull request #3680 from hasezoey/addSqliteRowId
Browse files Browse the repository at this point in the history
feat(diesel_cli) sqlite use "rowid" if no explicit primary key is present
  • Loading branch information
weiznich authored Jul 7, 2023
2 parents 8a68b3f + 3e5edbf commit 13c2374
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 5 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ default features enabled using some set of dependencies. Those set of dependenci
an up to date version of the specific dependency. We check this by using the unstable `-Z minimal-version` cargo flag.
Increasing the minimal supported Rust version will always be coupled at least with a minor release.

## Unreleased
## Unreleased

### Added

* Added automatic usage of all sqlite `rowid` aliases when no explicit primary key is defined for `print-schema`

## [2.1.0] 2023-05-26

Expand Down
50 changes: 46 additions & 4 deletions diesel_cli/src/infer_schema_internals/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ struct ForeignKeyListRow {
_match: String,
}

/// All SQLite rowid aliases
/// Ordered by preference
/// https://www.sqlite.org/rowidtable.html
const SQLITE_ROWID_ALIASES: &[&str] = &["rowid", "oid", "_rowid_"];

pub fn get_primary_keys(
conn: &mut SqliteConnection,
table: &TableName,
Expand All @@ -200,10 +205,32 @@ pub fn get_primary_keys(
format!("PRAGMA TABLE_INFO('{}')", &table.sql_name)
};
let results = sql::<pragma_table_info::SqlType>(&query).load::<FullTableInfo>(conn)?;
Ok(results
.into_iter()
.filter_map(|i| if i.primary_key { Some(i.name) } else { None })
.collect())
let mut collected: Vec<String> = results
.iter()
.filter_map(|i| {
if i.primary_key {
Some(i.name.clone())
} else {
None
}
})
.collect();
// SQLite tables without "WITHOUT ROWID" always have aliases for the implicit PRIMARY KEY "rowid" and its aliases
// unless the user defines a column with those names, then the name in question refers to the created column
// https://www.sqlite.org/rowidtable.html
if collected.is_empty() {
for alias in SQLITE_ROWID_ALIASES {
if results.iter().any(|v| &v.name.as_str() == alias) {
continue;
}

// only add one alias as the primary key
collected.push(alias.to_string());
break;
}
// if it is still empty at this point, then a "diesel requires a primary key" error will be given
}
Ok(collected)
}

pub fn determine_column_type(
Expand Down Expand Up @@ -407,3 +434,18 @@ fn load_foreign_key_constraints_loads_foreign_keys() {
let fks = load_foreign_key_constraints(&mut connection, None).unwrap();
assert_eq!(vec![fk_one, fk_two], fks);
}

#[test]
fn all_rowid_aliases_used_empty_result() {
let mut connection = SqliteConnection::establish(":memory:").unwrap();

diesel::sql_query("CREATE TABLE table_1 (rowid TEXT, oid TEXT, _rowid_ TEXT)")
.execute(&mut connection)
.unwrap();

let table_1 = TableName::from_name("table_1");

let res = get_primary_keys(&mut connection, &table_1);
assert!(res.is_ok());
assert!(res.unwrap().is_empty());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[print_schema]
file = "src/schema.rs"
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
source: diesel_cli/tests/print_schema.rs
description: "Test: print_schema_sqlite_without_explicit_primary_key"
---
// @generated automatically by Diesel CLI.

diesel::table! {
no_explicit (rowid) {
rowid -> Integer,
name -> Text,
}
}

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

diesel::table! {
with_explicit_rowid_oid (_rowid_) {
_rowid_ -> Integer,
name -> Text,
rowid -> Text,
oid -> Text,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CREATE TABLE no_explicit (
name TEXT
);

CREATE TABLE with_explicit_rowid (
name TEXT,
rowid TEXT
);

CREATE TABLE with_explicit_rowid_oid (
name TEXT,
rowid TEXT,
oid TEXT
);

0 comments on commit 13c2374

Please sign in to comment.