Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQLite SaveChanges: Enable non-rowid store-generated keys #17497

Merged
merged 1 commit into from
Aug 29, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions EFCore.Sqlite.slnf
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
"src\\EFCore.Abstractions\\EFCore.Abstractions.csproj",
"src\\EFCore.Analyzers\\EFCore.Analyzers.csproj",
"src\\EFCore.Design\\EFCore.Design.csproj",
"src\\EFCore.InMemory\\EFCore.InMemory.csproj",
"src\\EFCore.Proxies\\EFCore.Proxies.csproj",
"src\\EFCore.Relational\\EFCore.Relational.csproj",
"src\\EFCore.Sqlite.Core\\EFCore.Sqlite.Core.csproj",
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ protected override void AppendIdentityWhereCondition(StringBuilder commandString
Check.NotNull(commandStringBuilder, nameof(commandStringBuilder));
Check.NotNull(columnModification, nameof(columnModification));

SqlGenerationHelper.DelimitIdentifier(commandStringBuilder, columnModification.ColumnName);
SqlGenerationHelper.DelimitIdentifier(commandStringBuilder, "rowid");
commandStringBuilder.Append(" = ")
.Append("last_insert_rowid()");
}
Original file line number Diff line number Diff line change
@@ -69,7 +69,7 @@ protected virtual void AppendInsertOperation_appends_insert_and_select_and_where
"SELECT " + OpenDelimiter + "Id" + CloseDelimiter + ", " + OpenDelimiter + "Computed" + CloseDelimiter + ""
+ Environment.NewLine +
"FROM " + SchemaPrefix + OpenDelimiter + "Ducks" + CloseDelimiter + "" + Environment.NewLine +
"WHERE " + RowsAffected + " = 1 AND " + OpenDelimiter + "Id" + CloseDelimiter + " = " + Identity + ";" + Environment.NewLine
"WHERE " + RowsAffected + " = 1 AND " + GetIdentityWhereCondition("Id") + ";" + Environment.NewLine
+ Environment.NewLine,
stringBuilder.ToString());
}
@@ -138,7 +138,7 @@ protected virtual void AppendInsertOperation_appends_insert_and_select_for_only_
"VALUES (@p0, @p1, @p2);" + Environment.NewLine +
"SELECT " + OpenDelimiter + "Id" + CloseDelimiter + "" + Environment.NewLine +
"FROM " + SchemaPrefix + OpenDelimiter + "Ducks" + CloseDelimiter + "" + Environment.NewLine +
"WHERE " + RowsAffected + " = 1 AND " + OpenDelimiter + "Id" + CloseDelimiter + " = " + Identity + ";" + Environment.NewLine
"WHERE " + RowsAffected + " = 1 AND " + GetIdentityWhereCondition("Id") + ";" + Environment.NewLine
+ Environment.NewLine,
stringBuilder.ToString());
}
@@ -163,7 +163,7 @@ protected virtual void AppendInsertOperation_appends_insert_and_select_for_all_s
"SELECT " + OpenDelimiter + "Id" + CloseDelimiter + ", " + OpenDelimiter + "Computed" + CloseDelimiter + ""
+ Environment.NewLine +
"FROM " + SchemaPrefix + OpenDelimiter + "Ducks" + CloseDelimiter + "" + Environment.NewLine +
"WHERE " + RowsAffected + " = 1 AND " + OpenDelimiter + "Id" + CloseDelimiter + " = " + Identity + ";" + Environment.NewLine
"WHERE " + RowsAffected + " = 1 AND " + GetIdentityWhereCondition("Id") + ";" + Environment.NewLine
+ Environment.NewLine,
stringBuilder.ToString());
}
@@ -187,7 +187,7 @@ protected virtual void AppendInsertOperation_appends_insert_and_select_for_only_
"DEFAULT VALUES;" + Environment.NewLine +
"SELECT " + OpenDelimiter + "Id" + CloseDelimiter + "" + Environment.NewLine +
"FROM " + SchemaPrefix + OpenDelimiter + "Ducks" + CloseDelimiter + "" + Environment.NewLine +
"WHERE " + RowsAffected + " = 1 AND " + OpenDelimiter + "Id" + CloseDelimiter + " = " + Identity + ";" + Environment.NewLine
"WHERE " + RowsAffected + " = 1 AND " + GetIdentityWhereCondition("Id") + ";" + Environment.NewLine
+ Environment.NewLine,
stringBuilder.ToString());
}
@@ -303,7 +303,7 @@ public virtual void GenerateNextSequenceValueOperation_correctly_handles_schemas

protected abstract string RowsAffected { get; }

protected abstract string Identity { get; }
protected virtual string Identity => throw new NotImplementedException();

protected virtual string OpenDelimiter => "\"";

@@ -314,6 +314,9 @@ public virtual void GenerateNextSequenceValueOperation_correctly_handles_schemas
protected virtual string SchemaPrefix =>
string.IsNullOrEmpty(Schema) ? string.Empty : OpenDelimiter + Schema + CloseDelimiter + ".";

protected virtual string GetIdentityWhereCondition(string columnName)
=> OpenDelimiter + columnName + CloseDelimiter + " = " + Identity;

protected ModificationCommand CreateInsertCommand(bool identityKey = true, bool isComputed = true, bool defaultsOnly = false)
{
var duckType = GetDuckType();
10 changes: 5 additions & 5 deletions test/EFCore.Sqlite.FunctionalTests/DataAnnotationSqliteTest.cs
Original file line number Diff line number Diff line change
@@ -165,7 +165,7 @@ public override void DatabaseGeneratedAttribute_autogenerates_values_when_set_to
VALUES (@p0, @p1, @p2, @p3, @p4);
SELECT ""UniqueNo""
FROM ""Sample""
WHERE changes() = 1 AND ""UniqueNo"" = last_insert_rowid();");
WHERE changes() = 1 AND ""rowid"" = last_insert_rowid();");
}

// Sqlite does not support length
@@ -189,7 +189,7 @@ public override void RequiredAttribute_for_navigation_throws_while_inserting_nul
VALUES (@p0, @p1);
SELECT ""Id""
FROM ""BookDetails""
WHERE changes() = 1 AND ""Id"" = last_insert_rowid();",
WHERE changes() = 1 AND ""rowid"" = last_insert_rowid();",
//
@"@p0=''
@p1='' (Nullable = false)
@@ -198,7 +198,7 @@ public override void RequiredAttribute_for_navigation_throws_while_inserting_nul
VALUES (@p0, @p1);
SELECT ""Id""
FROM ""BookDetails""
WHERE changes() = 1 AND ""Id"" = last_insert_rowid();");
WHERE changes() = 1 AND ""rowid"" = last_insert_rowid();");
}

public override void RequiredAttribute_for_property_throws_while_inserting_null_value()
@@ -216,7 +216,7 @@ public override void RequiredAttribute_for_property_throws_while_inserting_null_
VALUES (@p0, @p1, @p2, @p3, @p4);
SELECT ""UniqueNo""
FROM ""Sample""
WHERE changes() = 1 AND ""UniqueNo"" = last_insert_rowid();",
WHERE changes() = 1 AND ""rowid"" = last_insert_rowid();",
//
@"@p0=''
@p1='' (Nullable = false)
@@ -228,7 +228,7 @@ public override void RequiredAttribute_for_property_throws_while_inserting_null_
VALUES (@p0, @p1, @p2, @p3, @p4);
SELECT ""UniqueNo""
FROM ""Sample""
WHERE changes() = 1 AND ""UniqueNo"" = last_insert_rowid();");
WHERE changes() = 1 AND ""rowid"" = last_insert_rowid();");
}

// Sqlite does not support length
25 changes: 25 additions & 0 deletions test/EFCore.Sqlite.FunctionalTests/StoreGeneratedSqliteTest.cs
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Xunit;

namespace Microsoft.EntityFrameworkCore
{
@@ -20,6 +21,21 @@ public override void Fields_used_correctly_for_store_generated_values()
// Computed columns not supported
}

[ConditionalFact]
public void Identity_key_works_when_not_aliasing_rowid()
{
ExecuteWithStrategyInTransaction(
context =>
{
var entry = context.Add(new Zach());

context.SaveChanges();
var id = entry.Entity.Id;

Assert.Equal(16, id?.Length ?? 0);
});
}

protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction)
=> facade.UseTransaction(transaction.GetDbTransaction());

@@ -98,8 +114,17 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
b.Property(e => e.NullableBackedInt).HasDefaultValue(-1);
});

modelBuilder.Entity<Zach>().Property(e => e.Id)
.ValueGeneratedOnAdd()
.HasDefaultValueSql("randomblob(16)");

base.OnModelCreating(modelBuilder, context);
}
}

private class Zach
{
public byte[] Id { get; set; }
}
}
}
Original file line number Diff line number Diff line change
@@ -23,9 +23,11 @@ protected override IUpdateSqlGenerator CreateSqlGenerator()
protected override TestHelpers TestHelpers => SqliteTestHelpers.Instance;

protected override string RowsAffected => "changes()";
protected override string Identity => "last_insert_rowid()";
protected override string Schema => null;

protected override string GetIdentityWhereCondition(string columnName)
=> OpenDelimiter + "rowid" + CloseDelimiter + " = last_insert_rowid()";

public override void GenerateNextSequenceValueOperation_correctly_handles_schemas()
{
var ex = Assert.Throws<NotSupportedException>(() => base.GenerateNextSequenceValueOperation_correctly_handles_schemas());