using System ;
using System.Collections.Generic ;
using System.Linq ;
using Microsoft.EntityFrameworkCore.Metadata ;
using Microsoft.EntityFrameworkCore.Migrations ;
using Microsoft.EntityFrameworkCore.Scaffolding.Metadata ;
using Xunit ;
namespace EntityFrameworkCore.Jet.Design.FunctionalTests
{
public class JetDatabaseModelFactoryTest : IClassFixture < JetDatabaseModelFixture >
{
[Fact]
public void It_reads_tables ( )
{
var sql = new List < string >
{
"CREATE TABLE [Everest] ( id int );" ,
"CREATE TABLE [Denali] ( id int );"
} ;
var dbInfo = CreateModel ( sql , new List < string > { "Everest" , "Denali" } ) ;
Assert . Collection ( dbInfo . Tables . OrderBy ( t = > t . Name ) ,
d = >
{
Assert . Equal ( "Jet" , d . Schema ) ;
Assert . Equal ( "Denali" , d . Name ) ;
} ,
e = >
{
Assert . Equal ( "Jet" , e . Schema ) ;
Assert . Equal ( "Everest" , e . Name ) ;
} ) ;
}
[Fact]
public void It_reads_foreign_keys ( )
{
var sql = new List < string > {
"CREATE TABLE Ranges ( Id INT IDENTITY (1,1) PRIMARY KEY);" ,
"CREATE TABLE Mountains ( RangeId INT NOT NULL, FOREIGN KEY (RangeId) REFERENCES Ranges(Id) ON DELETE CASCADE)"
} ;
var dbInfo = CreateModel ( sql , new List < string > { "Ranges" , "Mountains" } ) ;
var fk = Assert . Single ( dbInfo . Tables . Single ( t = > t . ForeignKeys . Count > 0 ) . ForeignKeys ) ;
Assert . Equal ( "Jet" , fk . Table . Schema ) ;
Assert . Equal ( "Mountains" , fk . Table . Name ) ;
Assert . Equal ( "Jet" , fk . PrincipalTable . Schema ) ;
Assert . Equal ( "Ranges" , fk . PrincipalTable . Name ) ;
Assert . Equal ( "RangeId" , fk . Columns . Single ( ) . Name ) ;
Assert . Equal ( "Id" , fk . PrincipalColumns . Single ( ) . Name ) ;
Assert . Equal ( ReferentialAction . Cascade , fk . OnDelete ) ;
}
[Fact]
public void It_reads_composite_foreign_keys ( )
{
var sql = new List < string > {
"CREATE TABLE Ranges1 ( Id INT IDENTITY (1,1), AltId INT, PRIMARY KEY(Id, AltId));" ,
"CREATE TABLE Mountains1 ( RangeId INT NOT NULL, RangeAltId INT NOT NULL, FOREIGN KEY (RangeId, RangeAltId) REFERENCES Ranges1(Id, AltId) ON DELETE NO ACTION)"
} ;
var dbInfo = CreateModel ( sql , new List < string > { "Ranges1" , "Mountains1" } ) ;
var fk = Assert . Single ( dbInfo . Tables . Single ( t = > t . ForeignKeys . Count > 0 ) . ForeignKeys ) ;
Assert . Equal ( "Jet" , fk . Table . Schema ) ;
Assert . Equal ( "Mountains1" , fk . Table . Name ) ;
Assert . Equal ( "Jet" , fk . PrincipalTable . Schema ) ;
Assert . Equal ( "Ranges1" , fk . PrincipalTable . Name ) ;
Assert . Equal ( new [ ] { "RangeId" , "RangeAltId" } , fk . Columns . Select ( c = > c . Name ) . ToArray ( ) ) ;
Assert . Equal ( new [ ] { "Id" , "AltId" } , fk . PrincipalColumns . Select ( c = > c . Name ) . ToArray ( ) ) ;
Assert . Equal ( ReferentialAction . NoAction , fk . OnDelete ) ;
}
[Fact]
public void It_reads_primary_keys ( )
{
var sql = new List < string >
{
"CREATE TABLE Place1 ( Id int, Name int, Location int);" ,
"CREATE UNIQUE INDEX IX_Name ON Place1 (Name);" ,
"CREATE INDEX IX_Location_Name ON Place1 (Location, Name);" ,
"CREATE INDEX IX_Location ON Place1 (Location);" ,
"ALTER TABLE Place1 ADD CONSTRAINT PK_Place1 PRIMARY KEY (Id);"
} ;
var dbModel = CreateModel ( sql , new List < string > { "Place1" } ) ;
var pkIndex = dbModel . Tables . Single ( ) . PrimaryKey ;
Assert . Equal ( "Jet" , pkIndex . Table . Schema ) ;
Assert . Equal ( "Place1" , pkIndex . Table . Name ) ;
Assert . StartsWith ( "PK_Place1" , pkIndex . Name ) ;
Assert . Equal ( new List < string > { "Id" } , pkIndex . Columns . Select ( ic = > ic . Name ) . ToList ( ) ) ;
}
[Fact]
public void It_reads_unique_constraints ( )
{
var sql = new List < string >
{
"CREATE TABLE Place2 ( Id int PRIMARY KEY, Name int, Location int );" ,
"CREATE UNIQUE INDEX IX_Name ON Place2 (Name);" ,
"CREATE INDEX IX_Location ON Place2 (Location);"
} ;
var dbModel = CreateModel ( sql , new List < string > { "Place2" } ) ;
var indexes = dbModel . Tables . Single ( ) . UniqueConstraints ;
Assert . All (
indexes , c = >
{
Assert . Equal ( "Jet" , c . Table . Schema ) ;
Assert . Equal ( "Place2" , c . Table . Name ) ;
} ) ;
Assert . Collection (
indexes ,
unique = >
{
Assert . Equal ( "Name" , unique . Columns . Single ( ) . Name ) ;
} ) ;
}
[Fact]
public void It_reads_indexes ( )
{
var sql = new List < string >
{
"CREATE TABLE Place ( Id int PRIMARY KEY, Name int, Location int );" ,
"CREATE UNIQUE INDEX IX_Name ON Place (Name);" ,
"CREATE INDEX IX_Location ON Place (Location);"
} ;
var dbInfo = CreateModel ( sql , new List < string > { "Place" } ) ;
var indexes = dbInfo . Tables . Single ( ) . Indexes ;
Assert . All ( indexes , c = >
{
Assert . Equal ( "Jet" , c . Table . Schema ) ;
Assert . Equal ( "Place" , c . Table . Name ) ;
} ) ;
Assert . Collection ( indexes ,
nonClustered = >
{
Assert . Equal ( "IX_Location" , nonClustered . Name ) ;
Assert . Equal ( "Location" , nonClustered . Columns . Select ( c = > c . Name ) . Single ( ) ) ;
} ) ;
}
[Fact]
public void It_reads_columns ( )
{
var sql = @ "
CREATE TABLE [ MountainsColumns ] (
Id int NOT NULL ,
Name varchar ( 100 ) NOT NULL ,
Latitude decimal ( 5 , 2 ) DEFAULT 0.0 ,
Created datetime DEFAULT # 09 / 15 / 1969 # ,
DiscoveredDate datetime ,
Modified varbinary ( 8 ) ,
CONSTRAINT PK_MountainsColumns PRIMARY KEY ( Name , Id )
) ; ";
var dbModel = CreateModel ( new List < string > { sql } , new List < string > { "MountainsColumns" } ) ;
var columns = dbModel . Tables . Single ( ) . Columns ;
Assert . All (
columns , c = >
{
Assert . Equal ( "Jet" , c . Table . Schema ) ;
Assert . Equal ( "MountainsColumns" , c . Table . Name ) ;
} ) ;
Assert . Collection (
columns ,
id = >
{
Assert . Equal ( "Id" , id . Name ) ;
Assert . Equal ( "int" , id . StoreType ) ;
Assert . False ( id . IsNullable ) ;
Assert . Null ( id . DefaultValueSql ) ;
} ,
name = >
{
Assert . Equal ( "Name" , name . Name ) ;
Assert . Equal ( "varchar(100)" , name . StoreType ) ;
Assert . False ( name . IsNullable ) ;
Assert . Null ( name . DefaultValueSql ) ;
} ,
lat = >
{
Assert . Equal ( "Latitude" , lat . Name ) ;
Assert . Equal ( "decimal(5, 2)" , lat . StoreType ) ;
Assert . True ( lat . IsNullable ) ;
Assert . Equal ( "0.0" , lat . DefaultValueSql ) ;
} ,
created = >
{
Assert . Equal ( "Created" , created . Name ) ;
Assert . Equal ( "datetime" , created . StoreType ) ;
Assert . True ( created . IsNullable ) ;
Assert . Equal ( "#09/15/1969#" , created . DefaultValueSql ) ;
} ,
discovered = >
{
Assert . Equal ( "DiscoveredDate" , discovered . Name ) ;
Assert . Equal ( "datetime" , discovered . StoreType ) ;
Assert . True ( discovered . IsNullable ) ;
Assert . Null ( discovered . DefaultValueSql ) ;
} ,
modified = >
{
Assert . Equal ( "Modified" , modified . Name ) ;
// This is a rowversion test. Rowversion is not supported by JET
//Assert.Equal(ValueGenerated.OnAddOrUpdate, modified.ValueGenerated);
Assert . Equal ( "varbinary(8)" , modified . StoreType ) ;
} ) ;
}
[Theory]
[InlineData("varchar(55)", 55)]
[InlineData("char(14)", 14)]
[InlineData("text", null)]
public void It_reads_max_length ( string type , int? length )
{
var tables = _fixture . Query < string > ( "SHOW Tables WHERE Name = 'Strings'" ) ;
if ( tables . Count ( ) > 0 )
{
_fixture . ExecuteNonQuery ( "DROP TABLE [Strings];" ) ;
}
var sql = new List < string >
{
"CREATE TABLE [Strings] ( CharColumn " + type + ");"
} ;
var db = CreateModel ( sql , new List < string > { "Strings" } ) ;
Assert . Equal ( type , db . Tables . Single ( ) . Columns . Single ( ) . StoreType ) ;
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void It_reads_identity ( bool isIdentity )
{
var tables = _fixture . Query < string > ( "SHOW Tables WHERE Name = 'Identities'" ) ;
if ( tables . Count ( ) > 0 )
{
_fixture . ExecuteNonQuery ( "DROP TABLE [Identities];" ) ;
}
var sql = new List < string >
{
"CREATE TABLE [Identities] ( Id INT " + ( isIdentity ? "IDENTITY(1,1)" : "" ) + ")"
} ;
var dbModel = CreateModel ( sql , new List < string > { "Identities" } ) ;
var column = Assert . Single ( dbModel . Tables . Single ( ) . Columns ) ;
// ReSharper disable once AssignNullToNotNullAttribute
Assert . Equal ( isIdentity ? ValueGenerated . OnAdd : default ( ValueGenerated ? ) , column . ValueGenerated ) ;
}
[Fact]
public void It_filters_tables ( )
{
var sql = new List < string >
{
"CREATE TABLE [K2] ( Id int, A varchar, UNIQUE (A) );" ,
"CREATE TABLE [Kilimanjaro] ( Id int,B varchar, UNIQUE (B ), FOREIGN KEY (B) REFERENCES K2 (A) );"
} ;
var selectionSet = new List < string > { "K2" } ;
var dbModel = CreateModel ( sql , selectionSet ) ;
var table = Assert . Single ( dbModel . Tables ) ;
// ReSharper disable once PossibleNullReferenceException
Assert . Equal ( "K2" , table . Name ) ;
Assert . Equal ( 2 , table . Columns . Count ) ;
Assert . Equal ( 1 , table . UniqueConstraints . Count ) ;
Assert . Empty ( table . ForeignKeys ) ;
}
private readonly JetDatabaseModelFixture _fixture ;
public DatabaseModel CreateModel ( List < string > createSql , IEnumerable < string > tables = null )
= > _fixture . CreateModel ( createSql , tables ) ;
public JetDatabaseModelFactoryTest ( JetDatabaseModelFixture fixture )
{
_fixture = fixture ;
}
}
}