Skip to content

Commit

Permalink
fix(schema-engine): fix sqlite migrations on D1 (#4871)
Browse files Browse the repository at this point in the history
* fix(schema-engine): make "migrate diff" deterministic

* ok

* fix(schema-engine): combine foreign_keys + defer_foreign_keys PRAGMAs to fix prisma/prisma#24208
  • Loading branch information
jkomyno committed May 28, 2024
1 parent 009080f commit cb3b66c
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 7 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions schema-engine/connectors/sql-schema-connector/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ tokio.workspace = true
serde.workspace = true
indoc.workspace = true
uuid.workspace = true
indexmap.workspace = true

prisma-value = { path = "../../../libs/prisma-value" }
schema-connector = { path = "../schema-connector" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,21 @@ impl SqlRenderer for SqliteFlavour {
}

fn render_redefine_tables(&self, tables: &[RedefineTable], schemas: MigrationPair<&SqlSchema>) -> Vec<String> {
// Based on 'Making Other Kinds Of Table Schema Changes' from https://www.sqlite.org/lang_altertable.html
let mut result = vec!["PRAGMA foreign_keys=OFF".to_string()];
// Based on 'Making Other Kinds Of Table Schema Changes' from https://www.sqlite.org/lang_altertable.html,
// and on https://developers.cloudflare.com/d1/reference/database-commands/#pragma-defer_foreign_keys--onoff.
let mut result: Vec<String> = vec![];

// disables foreign key constraint enforcement
result.push("PRAGMA defer_foreign_keys=ON".to_string());
result.push("PRAGMA foreign_keys=OFF".to_string());

let mut foreign_key_checks = vec![];

for redefine_table in tables {
let tables = schemas.walk(redefine_table.table_ids);
let temporary_table_name = format!("new_{}", &tables.next.name());

// maybe use render_create_table_for_migration?
result.push(self.render_create_table_as(
tables.next,
QuotedWithPrefix(None, Quoted::sqlite_ident(&temporary_table_name)),
Expand Down Expand Up @@ -218,9 +225,13 @@ impl SqlRenderer for SqliteFlavour {
));
}

result.extend(foreign_key_checks);
// Checks the database for foreign key constraint violations.
// Note: this code is probably useless, pending foreign constraint violations are checked fine even without it.
// result.extend(foreign_key_checks);

// resumes immediate enforcement of foreign key constraints.
result.push("PRAGMA foreign_keys=ON".to_string());
result.push("PRAGMA defer_foreign_keys=OFF".to_string());

result
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{column, enums::EnumDiffer, table::TableDiffer};
use crate::{flavour::SqlFlavour, migration_pair::MigrationPair, SqlDatabaseSchema};
use indexmap::IndexMap;
use sql_schema_describer::{
postgres::{ExtensionId, ExtensionWalker, PostgresSchemaExt},
walkers::{EnumWalker, TableColumnWalker, TableWalker},
Expand All @@ -18,9 +19,9 @@ pub(crate) struct DifferDatabase<'a> {
/// The schemas being diffed
pub(crate) schemas: MigrationPair<&'a SqlDatabaseSchema>,
/// Namespace name -> namespace indexes.
namespaces: HashMap<Cow<'a, str>, MigrationPair<Option<NamespaceId>>>,
namespaces: IndexMap<Cow<'a, str>, MigrationPair<Option<NamespaceId>>>,
/// Table name -> table indexes.
tables: HashMap<Table<'a>, MigrationPair<Option<TableId>>>,
tables: IndexMap<Table<'a>, MigrationPair<Option<TableId>>>,
/// (table_idxs, column_name) -> column_idxs. BTreeMap because we want range
/// queries (-> all the columns in a table).
columns: BTreeMap<(MigrationPair<TableId>, &'a str), MigrationPair<Option<TableColumnId>>>,
Expand All @@ -47,8 +48,8 @@ impl<'a> DifferDatabase<'a> {
let mut db = DifferDatabase {
flavour,
schemas,
namespaces: HashMap::with_capacity(namespace_count_lb),
tables: HashMap::with_capacity(table_count_lb),
namespaces: IndexMap::with_capacity(namespace_count_lb),
tables: IndexMap::with_capacity(table_count_lb),
columns: BTreeMap::new(),
column_changes: Default::default(),
extensions: Default::default(),
Expand Down

0 comments on commit cb3b66c

Please sign in to comment.