Compare commits

...

1 Commits

Author SHA1 Message Date
Sebastien Ros
8be940fe8d Reviving the SQLite 2015-09-04 17:44:54 -07:00
33 changed files with 21694 additions and 39 deletions

2
.gitignore vendored
View File

@@ -166,6 +166,8 @@ build/
/artifacts
*.sln.cache
src/Orchard.Web/Media/*
src/Orchard.Web/x86
src/Orchard.Web/amd64
log.xml
profiling/
*.orig

View File

@@ -265,6 +265,18 @@ Website: https://github.com/sayedihashimi/package-web/
Copyright: Copyright 2013 Sayed Ibrahim Hashimi
License: Apache 2.0
SQLite
-----
Website: http://sqlite.org
Copyright: Public Domain
License: Public Domain
SQLite CREATE Statement Parser for .Net
-----
Website: https://github.com/ericschultz/SQLiteParser
Copyright: Copyright 2014 Outercurve Foundation
License: MIT
SpecFlow
-----
Website: http://www.specflow.org/

View File

@@ -10,6 +10,7 @@
<MsBuildTasksFolder>$(MSBuildProjectDirectory)\buildtasks</MsBuildTasksFolder>
<ArtifactsFolder>$(MSBuildProjectDirectory)\artifacts</ArtifactsFolder>
<SqlCeFolder>$(MSBuildProjectDirectory)\lib\sqlce</SqlCeFolder>
<SQLiteFolder>$(MSBuildProjectDirectory)\lib\sqlite</SQLiteFolder>
<SourceArtifactFolder>$(ArtifactsFolder)\Source</SourceArtifactFolder>
<MsDeployArtifactFolder>$(ArtifactsFolder)\MsDeploy</MsDeployArtifactFolder>
<GalleryArtifactFolder>$(ArtifactsFolder)\Gallery</GalleryArtifactFolder>
@@ -189,6 +190,8 @@
<ItemGroup>
<SqlCe-Native-Binaries-x86 Include="$(SqlCeFolder)\x86\**\*"/>
<SqlCe-Native-Binaries-amd64 Include="$(SqlCeFolder)\amd64\**\*"/>
<SQLite-Native-Binaries-x86 Include="$(SQLiteFolder)\x86\**\*"/>
<SQLite-Native-Binaries-amd64 Include="$(SQLiteFolder)\amd64\**\*"/>
<Stage-Orchard-Web-Bins Include="$(WebSitesFolder)\Orchard.Web\bin\*"/>
<Stage-Bin-Exclude Include="$(WebSitesFolder)\**\bin\**\*" />
<Stage-Web Include="$(WebSitesFolder)\Orchard.Web\**\*;$(SrcFolder)\Orchard.Web\*.csproj;" Exclude="$(SrcFolder)\Orchard.Web\Orchard.Web.csproj;$(SrcFolder)\Orchard.Web\**\*.Release.config;$(SrcFolder)\Orchard.Web\**\*.Debug.config"/>
@@ -259,6 +262,8 @@
<Copy SourceFiles="@(Stage-PoFiles)" DestinationFolder="$(StageFolder)\%(RecursiveDir)"/>
<Copy SourceFiles="@(SqlCe-Native-Binaries-x86)" DestinationFolder="$(StageFolder)\bin\x86\%(RecursiveDir)"/>
<Copy SourceFiles="@(SqlCe-Native-Binaries-amd64)" DestinationFolder="$(StageFolder)\bin\amd64\%(RecursiveDir)"/>
<Copy SourceFiles="@(SQLite-Native-Binaries-x86)" DestinationFolder="$(StageFolder)\bin\x86\%(RecursiveDir)"/>
<Copy SourceFiles="@(SQLite-Native-Binaries-amd64)" DestinationFolder="$(StageFolder)\bin\amd64\%(RecursiveDir)"/>
<Copy SourceFiles="@(Stage-Core)" DestinationFolder="$(StageFolder)\Core\%(RecursiveDir)"/>
<Copy SourceFiles="@(Stage-Modules)" DestinationFiles="@(Stage-Modules->'$(StageFolder)\Modules\%(ModuleName)\%(RecursiveDir)%(Filename)%(Extension)')"/>
<Copy SourceFiles="@(Stage-Modules-Binaries-Unique)" DestinationFiles="@(Stage-Modules-Binaries-Unique->'$(StageFolder)\Modules\%(ModuleName)\%(RecursiveDir)%(Filename)%(Extension)')"/>

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Outercurve.SQLiteCreateTree</name>
</assembly>
<members>
<member name="M:Outercurve.SQLiteCreateTree.AlterTable.NativeAlterTableProcessor.CreateSqlStatements(Outercurve.SQLiteCreateTree.AlterTable.Action.AlterTableCommand)">
<summary>
returns null if something if we don't have ones we can do natively
</summary>
<param name="command"></param>
<returns></returns>
</member>
<member name="P:Outercurve.SQLiteCreateTree.Nodes.ColumnConstraint.UniqueConstraintNode.ConflictClause">
<summary>
Conflict Clause is really weird, it can be empty. We treat that as null.
</summary>
</member>
<member name="P:Outercurve.SQLiteCreateTree.Nodes.ForeignDeferrableNode.IsDeferrable">
<summary>
NOT?
</summary>
</member>
<member name="P:Outercurve.SQLiteCreateTree.Nodes.ForeignDeferrableNode.InitiallyImmediate">
<summary>
((INITIALLY DEFERRED)| (INITIALLY IMMEDIATE))?
</summary>
</member>
</members>
</doc>

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,121 @@
<?xml version="1.0"?>
<!--
*
* System.Data.SQLite.dll.config -
*
* Written by Joe Mistachkin.
* Released to the public domain, use at your own risk!
*
-->
<configuration>
<appSettings>
<!--
NOTE: If this configuration variable is set [to anything], the SQLite
logging subsystem may be initialized in a non-default application
domain. By default, this is not allowed due to the potential
for application domain unloading issues.
-->
<!--
<add key="Force_SQLiteLog" value="1" />
-->
<!--
NOTE: If this configuration variable is set [to anything], the native
library pre-loading functionality will be disabled. By default,
the native library pre-loading will attempt to load the native
SQLite library from architecture-specific (e.g. "x86", "amd64",
"x64") or platform-specific (e.g. "Win32") directories that
reside underneath the application base directory.
-->
<!--
<add key="No_PreLoadSQLite" value="1" />
-->
<!--
NOTE: If this configuration variable is set [to anything], the new
connection string parsing algorithm will not be used. This
environment variable is intended for use with legacy code only.
-->
<!--
<add key="No_SQLiteConnectionNewParser" value="1" />
-->
<!--
NOTE: If this configuration variable is set [to anything], the initial
search for types in all loaded assemblies that are tagged with
the SQLiteFunction attribute will be skipped. Normally, this
search is conducted only once per application domain by the
static constructor of the SQLiteFunction class; however, these
implementation details are subject to change.
-->
<!--
<add key="No_SQLiteFunctions" value="1" />
-->
<!--
NOTE: If this configuration variable is set [to anything], it will be
used instead of the application base directory by the native
library pre-loader. This environment variable can be especially
useful in ASP.NET and other hosted environments where direct
control of the location of the managed assemblies is not under
the control of the application.
-->
<!--
<add key="PreLoadSQLite_BaseDirectory" value="" />
-->
<!--
NOTE: If this configuration variable is set [to anything], it will be
used instead of the processor architecture value contained in the
PROCESSOR_ARCHITECTURE environment variable to help build the
path of the native library to pre-load.
-->
<!--
<add key="PreLoadSQLite_ProcessorArchitecture" value="x86" />
-->
<!--
NOTE: If this environment variable is set [to anything], the native
library pre-loading code will skip conducting a search for the
native library to pre-load. By default, the search starts in the
location of the currently executing assembly (i.e. the assembly
containing all the managed components for System.Data.SQLite) and
then falls back to the application domain base directory.
-->
<!--
<add key="PreLoadSQLite_NoSearchForDirectory" value="1" />
-->
<!--
NOTE: If this configuration variable is set [to anything], the location
of the currently executing assembly (i.e. the one containing all
the managed components for System.Data.SQLite) will be used as
the basis for locating the the native library to pre-load (i.e.
instead of using the application domain base directory).
-->
<!--
<add key="PreLoadSQLite_UseAssemblyDirectory" value="1" />
-->
<!--
NOTE: This configuration variable is normally set by the operating
system itself and should reflect the native processor
architecture of the current process (e.g. a 32-bit x86
application running on a 64-bit x64 operating system should have
the value "x86").
-->
<!--
<add key="PROCESSOR_ARCHITECTURE" value="%PROCESSOR_ARCHITECTURE%" />
-->
<!--
NOTE: If this environment variable is set [to anything], it will be
used by the System.Data.SQLite.SQLiteFactory class as the type
name containing the System.Data.Common.DbProviderServices
implementation that should be used.
-->
<!--
<add key="TypeName_SQLiteProviderServices" value="" />
-->
</appSettings>
</configuration>

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FluentNHibernate;
using FluentNHibernate.Automapping;
using FluentNHibernate.Automapping.Alterations;
using FluentNHibernate.Cfg;
using FluentNHibernate.Diagnostics;
using NHibernate;
using NHibernate.Tool.hbm2ddl;
using Orchard.Data;
using Orchard.Data.Providers;
using Orchard.Environment.ShellBuilders.Models;
namespace Orchard.Tests.DataMigration.SQLite {
public static class SQLiteDataUtility {
public static ISessionFactory CreateSessionFactory(string fileName, params Type[] types) {
//var persistenceModel = AutoMap.Source(new Types(types))
// .Alterations(alt => AddAlterations(alt, types))
// .Conventions.AddFromAssemblyOf<DataModule>();
var persistenceModel = AbstractDataServicesProvider.CreatePersistenceModel(types.Select(t => new RecordBlueprint { TableName = "Test_" + t.Name, Type = t }).ToList());
var persistenceConfigurer = new SQLiteDataServicesProvider(fileName).GetPersistenceConfigurer(true/*createDatabase*/);
return Fluently.Configure()
.Database(persistenceConfigurer)
.Mappings(m => m.AutoMappings.Add(persistenceModel))
.ExposeConfiguration(c => {
// This is to work around what looks to be an issue in the NHibernate driver:
// When inserting a row with IDENTITY column, the "SELET @@IDENTITY" statement
// is issued as a separate command. By default, it is also issued in a separate
// connection, which is not supported (returns NULL).
c.SetProperty("connection.release_mode", "on_close");
new SchemaExport(c).Create(false /*script*/, true /*export*/);
})
.BuildSessionFactory();
}
private static void AddAlterations(AutoMappingAlterationCollection alterations, IEnumerable<Type> types) {
foreach (var assembly in types.Select(t => t.Assembly).Distinct()) {
alterations.Add(new AutoMappingOverrideAlteration(assembly));
alterations.AddFromAssembly(assembly);
}
alterations.AddFromAssemblyOf<DataModule>();
}
public static ISessionFactory CreateSessionFactory(params Type[] types) {
return CreateSessionFactory(
types.Aggregate("db", (n, t) => t.FullName + "." + n),
types);
}
#region Nested type: Types
private class Types : ITypeSource {
private readonly IEnumerable<Type> _types;
public Types(params Type[] types) {
_types = types;
}
#region ITypeSource Members
public IEnumerable<Type> GetTypes() {
return _types;
}
public void LogSource(IDiagnosticLogger logger) {
throw new NotImplementedException();
}
public string GetIdentifier() {
throw new NotImplementedException();
}
#endregion
}
#endregion
}
}

View File

@@ -0,0 +1,210 @@
using System;
using System.Data;
using System.Linq;
using Autofac;
using NHibernate;
using NUnit.Framework;
using Orchard.Data;
using Orchard.Data.Migration.Interpreters;
using Orchard.Data.Migration.Schema;
using Orchard.Data.Providers;
using Orchard.Environment;
using Orchard.Environment.Configuration;
using Orchard.Environment.ShellBuilders.Models;
using Orchard.FileSystems.AppData;
using Orchard.Reports.Services;
using Orchard.Tests.ContentManagement;
using System.IO;
using Orchard.Tests.Environment;
using Orchard.Tests.FileSystems.AppData;
using Orchard.Tests.Stubs;
namespace Orchard.Tests.DataMigration.SQLite {
[TestFixture]
public class SQLiteSchemaBuilderTestsBase {
private IContainer _container;
private ISessionFactory _sessionFactory;
private string _databaseFileName;
private string _tempFolder;
private SchemaBuilder _schemaBuilder;
private DefaultDataMigrationInterpreter _interpreter;
private ISession _session;
[SetUp]
public void Setup() {
_databaseFileName = Path.GetTempFileName();
_sessionFactory = SQLiteDataUtility.CreateSessionFactory(_databaseFileName);
_tempFolder = Path.GetTempFileName();
File.Delete(_tempFolder);
var appDataFolder = AppDataFolderTests.CreateAppDataFolder(_tempFolder);
var builder = new ContainerBuilder();
_session = _sessionFactory.OpenSession();
builder.RegisterInstance(appDataFolder).As<IAppDataFolder>();
builder.RegisterType<SQLiteDataServicesProvider>().As<IDataServicesProvider>();
builder.RegisterType<DataServicesProviderFactory>().As<IDataServicesProviderFactory>();
builder.RegisterType<DefaultDataMigrationInterpreter>().As<IDataMigrationInterpreter>();
builder.RegisterType<SQLiteCommandInterpreter>().As<ICommandInterpreter>();
builder.RegisterType<SessionConfigurationCache>().As<ISessionConfigurationCache>();
builder.RegisterType<SessionFactoryHolder>().As<ISessionFactoryHolder>();
builder.RegisterType<DefaultDatabaseCacheConfiguration>().As<IDatabaseCacheConfiguration>();
builder.RegisterType<StubHostEnvironment>().As<IHostEnvironment>();
builder.RegisterInstance(new ShellBlueprint { Records = Enumerable.Empty<RecordBlueprint>() }).As<ShellBlueprint>();
builder.RegisterInstance(new ShellSettings { Name = "temp", DataProvider = "SQLite", DataTablePrefix = "TEST" }).As<ShellSettings>();
builder.RegisterType<DialectService>().As<IDialectService>();
builder.RegisterType<StubWorkContextAccessor>().As<IWorkContextAccessor>();
builder.RegisterModule(new DataModule());
_container = builder.Build();
_interpreter = _container.Resolve<IDataMigrationInterpreter>() as DefaultDataMigrationInterpreter;
_schemaBuilder = new SchemaBuilder(_interpreter);
}
[Test]
public void AllMethodsShouldBeCalledSuccessfully() {
_schemaBuilder
.CreateTable("User", table => table
.ContentPartRecord()
.Column("Firstname", DbType.String, column => column.WithLength(255))
.Column("Lastname", DbType.String, column => column.WithPrecision(0).WithScale(1)))
.CreateTable("Address", table => table
.ContentPartVersionRecord()
.Column("City", DbType.String)
.Column("ZIP", DbType.Int32, column => column.Unique())
.Column("UserId", DbType.Int32, column => column.NotNull()))
.CreateForeignKey("User_Address", "Address", new[] { "UserId" }, "User", new[] { "Id" })
.AlterTable("User", table => table
.AddColumn("Age", DbType.Int32))
.AlterTable("User", table => table
.DropColumn("Lastname"))
.AlterTable("User", table => table
.CreateIndex("IDX_XYZ", "Firstname"))
.AlterTable("User", table => table
.DropIndex("IDX_XYZ"))
.DropForeignKey("Address", "User_Address")
.DropTable("Address");
}
[Test]
public void CreateCommandShouldBeHandled() {
_schemaBuilder
.CreateTable("User", table => table
.Column("Id", DbType.Int32, column => column.PrimaryKey().Identity())
.Column("Firstname", DbType.String, column => column.WithLength(255))
.Column("Lastname", DbType.String, column => column.WithLength(100).NotNull())
.Column("SN", DbType.AnsiString, column => column.WithLength(40).Unique())
.Column("Salary", DbType.Decimal, column => column.WithPrecision(9).WithScale(2))
.Column("Gender", DbType.Decimal, column => column.WithDefault(""))
);
}
[Test]
public void DropTableCommandShouldBeHandled() {
_schemaBuilder
.CreateTable("User", table => table
.Column("Id", DbType.Int32, column => column.PrimaryKey().Identity())
.Column("Firstname", DbType.String, column => column.WithLength(255))
.Column("Lastname", DbType.String, column => column.WithLength(100).NotNull())
.Column("SN", DbType.AnsiString, column => column.WithLength(40).Unique())
.Column("Salary", DbType.Decimal, column => column.WithPrecision(9).WithScale(2))
.Column("Gender", DbType.Decimal, column => column.WithDefault(""))
);
_schemaBuilder
.DropTable("User");
}
[Test]
public void CustomSqlStatementsShouldBeHandled() {
_schemaBuilder
.ExecuteSql("select 1");
}
[Test]
public void AlterTableCommandShouldBeHandled() {
_schemaBuilder
.CreateTable("User", table => table
.Column("Firstname", DbType.String, column => column.WithLength(255))
.Column("Lastname", DbType.String, column => column.WithLength(100).NotNull()))
.AlterTable("User", table => table
.AddColumn("Age", DbType.Int32))
.AlterTable("User", table => table
.AlterColumn("Lastname", column => column.WithDefault("Doe")))
.AlterTable("User", table => table
.DropColumn("Firstname")
);
// creating a new row should assign a default value to Firstname and Age
_schemaBuilder.ExecuteSql("insert into TEST_User DEFAULT VALUES;");
// ensure we have one record with the default value
var query = _session.CreateSQLQuery("SELECT count() FROM TEST_User WHERE Lastname = 'Doe'");
Assert.That(query.UniqueResult<long>(), Is.EqualTo(1));
// ensure this is not a false positive
query = _session.CreateSQLQuery("SELECT count(*) FROM TEST_User WHERE Lastname = 'Foo'");
Assert.That(query.UniqueResult<long>(), Is.EqualTo(0));
}
[Test]
public void ForeignKeyShouldBeCreatedAndRemoved() {
_schemaBuilder
.CreateTable("User", table => table
.Column("Id", DbType.Int32, column => column.PrimaryKey().Identity())
.Column("Firstname", DbType.String, column => column.WithLength(255))
.Column("Lastname", DbType.String, column => column.WithPrecision(0).WithScale(1)))
.CreateTable("Address", table => table
.Column("City", DbType.String)
.Column("ZIP", DbType.Int32, column => column.Unique())
.Column("UserId", DbType.Int32, column => column.NotNull()))
.CreateForeignKey("FK_User", "Address", new[] { "UserId" }, "User", new[] { "Id" })
.DropForeignKey("Address", "FK_User");
}
[Test]
public void ShouldAllowFieldSizeAlteration() {
_schemaBuilder
.CreateTable("ContentItemRecord", table => table
.Column("Id", DbType.Int32, column => column.PrimaryKey().Identity())
.Column("Data", DbType.String, column => column.WithLength(255)));
// should write successfully less than 255 chars
_schemaBuilder
.ExecuteSql("insert into TEST_ContentItemRecord (Data) values('Hello World')");
_schemaBuilder
.AlterTable("ContentItemRecord", table => table
.AlterColumn("Data", column => column.WithType(DbType.String).WithLength(2048)));
// should write successfully a bigger value now
_schemaBuilder
.ExecuteSql(String.Format("insert into TEST_ContentItemRecord (Data) values('{0}')", new String('x', 2048)));
}
[Test]
public void PrecisionAndScaleAreApplied() {
_schemaBuilder
.CreateTable("Product", table => table
.Column("Price", DbType.Decimal, column => column.WithPrecision(19).WithScale(9))
);
_schemaBuilder
.ExecuteSql(String.Format("INSERT INTO TEST_Product (Price) VALUES ({0})", "123456.123456789"));
var query = _session.CreateSQLQuery("SELECT MAX(Price) FROM TEST_Product");
Assert.That(query.UniqueResult(), Is.EqualTo(123456.123456789m));
}
}
}

View File

@@ -120,6 +120,9 @@
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Data.SQLite">
<HintPath>..\..\lib\sqlite\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\..\lib\sqlce\System.Data.SqlServerCe.dll</HintPath>
<Private>True</Private>
@@ -215,6 +218,8 @@
<Compile Include="DatabaseEnabledTestsBase.cs" />
<Compile Include="DataMigration\SchemaBuilderTests.cs" />
<Compile Include="DataMigration\DataMigrationTests.cs" />
<Compile Include="DataMigration\SQLite\SQLiteDataUtility.cs" />
<Compile Include="DataMigration\SQLite\SQLiteSchemaBuilderTestsBase.cs" />
<Compile Include="DataMigration\Utilities\NullInterpreter.cs" />
<Compile Include="DataUtility.cs" />
<Compile Include="Data\Builders\SessionFactoryBuilderTests.cs" />
@@ -404,7 +409,16 @@
<Copy SourceFiles="@(SqlCeBinariesx86)" DestinationFolder="$(OutputPath)\x86\%(RecursiveDir)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(SqlCeBinariesx64)" DestinationFolder="$(OutputPath)\amd64\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>
<Target Name="CopySQLiteBinaries">
<ItemGroup>
<SQLiteBinariesx86 Include="$(ProjectDir)..\..\lib\sqlite\x86\**\*" />
<SQLiteBinariesx64 Include="$(ProjectDir)..\..\lib\sqlite\x64\**\*" />
</ItemGroup>
<Copy SourceFiles="@(SQLiteBinariesx86)" DestinationFolder="$(OutputPath)\x86\%(RecursiveDir)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(SQLiteBinariesx64)" DestinationFolder="$(OutputPath)\amd64\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>
<Target Name="AfterBuild">
<CallTarget Targets="CopySqlCeBinaries" />
<CallTarget Targets="CopySQLiteBinaries" />
</Target>
</Project>

View File

@@ -10,14 +10,17 @@ namespace Orchard.Alias {
.Column<string>("Path", c => c.WithLength(2048))
.Column<int>("Action_id")
.Column<string>("RouteValues", c => c.Unlimited())
.Column<string>("Source", c => c.WithLength(256)))
.Column<string>("Source", c => c.WithLength(256))
.Column<bool>("IsManaged", column => column.WithDefault(false))
)
.CreateTable("ActionRecord",
table => table
.Column<int>("Id", column => column.PrimaryKey().Identity())
.Column<string>("Area")
.Column<string>("Controller")
.Column<string>("Action"));
return 1;
.Column<string>("Action")
);
return 2;
}
public int UpdateFrom1() {

View File

@@ -9,6 +9,7 @@ using Orchard.Setup.ViewModels;
using Orchard.Localization;
using Orchard.Themes;
using Orchard.UI.Notify;
using Orchard.Utility.Extensions;
namespace Orchard.Setup.Controllers {
[ValidateInput(false), Themed]
@@ -72,20 +73,18 @@ namespace Orchard.Setup.Controllers {
[HttpPost, ActionName("Index")]
public ActionResult IndexPOST(SetupViewModel model) {
// Sets the setup request timeout to 10 minutes to give enough time to execute custom recipes.
HttpContext.Server.ScriptTimeout = 600;
var recipes = _setupService.Recipes().ToList();
// If no builtin provider, a connection string is mandatory.
if (model.DatabaseProvider != SetupDatabaseType.Builtin && string.IsNullOrEmpty(model.DatabaseConnectionString))
if ((model.DatabaseProvider != SetupDatabaseType.Builtin && model.DatabaseProvider != SetupDatabaseType.SQLite) && string.IsNullOrEmpty(model.DatabaseConnectionString))
ModelState.AddModelError("DatabaseConnectionString", T("A connection string is required.").Text);
if (!String.IsNullOrWhiteSpace(model.ConfirmPassword) && model.AdminPassword != model.ConfirmPassword) {
ModelState.AddModelError("ConfirmPassword", T("Password confirmation must match.").Text);
}
if (model.DatabaseProvider != SetupDatabaseType.Builtin && !string.IsNullOrWhiteSpace(model.DatabaseTablePrefix)) {
if ((model.DatabaseProvider != SetupDatabaseType.Builtin && model.DatabaseProvider != SetupDatabaseType.SQLite) && !String.IsNullOrWhiteSpace(model.DatabaseTablePrefix))
{
model.DatabaseTablePrefix = model.DatabaseTablePrefix.Trim();
if (!Char.IsLetter(model.DatabaseTablePrefix[0])) {
ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must begin with a letter.").Text);
@@ -128,9 +127,9 @@ namespace Orchard.Setup.Controllers {
case SetupDatabaseType.MySql:
providerName = "MySql";
break;
case SetupDatabaseType.PostgreSql:
providerName = "PostgreSql";
case SetupDatabaseType.SQLite:
providerName = "SQLite";
break;
break;
default:

View File

@@ -19,6 +19,35 @@
var description = $(this).find(":selected").data("recipe-description"); // reads the html attribute of the selected option
$("#recipedescription").text(description); // make the contents of <div id="recipe-description"></div> be the escaped description string
});
$(".data").find('input[name=DatabaseProvider]:checked').click();
$(".embedded").change(function() {
alert($(this).find(":selected").attr("selected"));
});
var handleVisibility = function() {
if ($("#sqlserver").is(":checked") || $("#mysql").is(":checked")) {
$("#databaseDetails").show();
if ($("#sqlserver").is(":checked")) {
$("#sqlserverDetails").show();
$("#mysqlDetails").hide();
} else {
$("#sqlserverDetails").hide();
$("#mysqlDetails").show();
}
} else {
$("#databaseDetails").hide();
}
};
$("input[name='DatabaseProvider']").change(handleVisibility);
var ourClicked = $("input[name='DatabaseProvider'][checked='checked']");
$("input[name='DatabaseProvider']").not("[checked='checked']")[0].click();
ourClicked.click();
});
})(jQuery);

View File

@@ -6,5 +6,6 @@
SqlServer,
MySql,
PostgreSql,
SQLite,
}
}

View File

@@ -36,11 +36,11 @@
</div>
<div>
<label for="AdminPassword">@T("Choose a password:")</label>
@Html.PasswordFor(svm => svm.AdminPassword, new { @class = "text single-line" })
@Html.PasswordFor(svm => svm.AdminPassword, new { @class = "text-box single-line" })
</div>
<div>
<label for="ConfirmAdminPassword">@T("Confirm the password:")</label>
@Html.PasswordFor(svm => svm.ConfirmPassword, new { @class = "text single-line" })
@Html.PasswordFor(svm => svm.ConfirmPassword, new { @class = "text-box single-line" })
</div>
</fieldset>
if (!Model.DatabaseIsPreconfigured) {
@@ -48,11 +48,15 @@ if (!Model.DatabaseIsPreconfigured) {
<legend>@T("How would you like to store your data?")</legend>
@Html.ValidationMessage("DatabaseOptions", "Unable to setup data storage.")
<div>
@Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.Builtin.ToString(), new { id = "builtin" })
@Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.Builtin.ToString(), new { id = "builtin"})
<label for="builtin" class="forcheckbox">@T("Use built-in data storage (SQL Server Compact)")</label>
</div>
<div>
@Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.SqlServer.ToString(), new { id = "sqlserver" })
@Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.SQLite.ToString(), new { id = "sqlite" })
<label for="sqlite" class="forcheckbox">@T("Use an embedded SQLite database")</label>
</div>
<div>
@Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.SqlServer.ToString(), new { id = "sqlserver"})
<label for="sqlserver" class="forcheckbox">@T("Use an existing SQL Server, SQL Express database")</label>
</div>
<div>
@@ -63,13 +67,13 @@ if (!Model.DatabaseIsPreconfigured) {
@Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.PostgreSql.ToString(), new { id = "postgresql" })
<label for="postgresql" class="forcheckbox">@T("Use an existing PostgreSQL database")</label>
</div>
<div data-controllerid="builtin" data-defaultstate="hidden">
<div>
<label for="DatabaseConnectionString">@T("Connection string")</label>
@Html.EditorFor(svm => svm.DatabaseConnectionString)
<span data-controllerid="sqlserver" class="hint databaseTypeHint">
<span class="hint databaseTypeHint" id="sqlserverDetails">
@T("Data Source=sqlServerName;Initial Catalog=dbName;User ID=userName;Password=password")
</span>
<span data-controllerid="mysql" class="hint databaseTypeHint">
<span class="hint databaseTypeHint" id="mysqlDetails">
@T("Data Source=serverName;Database=dbName;User Id=userName;Password=password")
</span>
<span data-controllerid="postgresql" class="hint databaseTypeHint">

View File

@@ -87,6 +87,9 @@
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data.SQLite">
<HintPath>..\..\lib\sqlite\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\..\lib\sqlce\System.Data.SqlServerCe.dll</HintPath>
<Private>True</Private>
@@ -275,12 +278,25 @@
<Copy SourceFiles="@(SqlCeBinariesx86)" DestinationFolder="$(OutputPath)\x86\%(RecursiveDir)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(SqlCeBinariesx64)" DestinationFolder="$(OutputPath)\amd64\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>
<Target Name="CopySQLiteBinaries">
<ItemGroup>
<SQLiteBinariesx86 Include="$(ProjectDir)..\..\lib\sqlite\x86\**\*" />
<SQLiteBinariesx64 Include="$(ProjectDir)..\..\lib\sqlite\x64\**\*" />
</ItemGroup>
<Copy SourceFiles="@(SQLiteBinariesx86)" DestinationFolder="$(OutputPath)\x86\%(RecursiveDir)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(SQLiteBinariesx64)" DestinationFolder="$(OutputPath)\amd64\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>
<Target Name="CleanSQLiteBinaries">
<RemoveDir Directories="$(ProjectDir)\x86"/>
<RemoveDir Directories="$(ProjectDir)\x64"/>
</Target>
<Target Name="AfterBuild" DependsOnTargets="MvcBuildViews">
<PropertyGroup>
<AreasManifestDir>$(ProjectDir)\..\Manifests</AreasManifestDir>
</PropertyGroup>
<CallTarget Targets="ExcludeRootBinariesDeployment" />
<CallTarget Targets="CopySqlCeBinaries" />
<CallTarget Targets="CopySQLiteBinaries" />
<!-- If this is an area child project, uncomment the following line:
<CreateAreaManifest AreaName="$(AssemblyName)" AreaType="Child" AreaPath="$(ProjectDir)" ManifestPath="$(AreasManifestDir)" ContentFiles="@(Content)" />
-->
@@ -289,4 +305,7 @@
<CopyAreaManifests ManifestPath="$(AreasManifestDir)" CrossCopy="false" RenameViews="true" />
-->
</Target>
<Target Name="AfterClean">
<CallTarget Targets="CleanSQLiteBinaries"/>
</Target>
</Project>

View File

@@ -270,6 +270,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gulp", "Gulp", "{90EBEE36-B
EndProjectSection
EndProject
Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CodeCoverage|Any CPU = CodeCoverage|Any CPU
Coverage|Any CPU = Coverage|Any CPU

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate.Cfg;
using NHibernate.Dialect;
namespace Orchard.Data.Migration.Interpreters
{
public interface IDialectService : IDependency {
Dialect GetDialect(Configuration config);
}
public class DialectService : IDialectService
{
public Dialect GetDialect(Configuration config) {
return Dialect.GetDialect(config.Properties);
}
}
}

View File

@@ -1,40 +1,311 @@
using Orchard.Data.Migration.Schema;
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using NHibernate;
using NHibernate.Dialect;
using NHibernate.SqlTypes;
using Orchard.ContentManagement.Records;
using Orchard.Data.Migration.Schema;
using Orchard.Environment.Configuration;
using Outercurve.SQLiteCreateTree;
using Outercurve.SQLiteCreateTree.AlterTable;
using Outercurve.SQLiteCreateTree.Nodes;
using Outercurve.SQLiteCreateTree.Nodes.ColumnConstraint;
using OcfAction = Outercurve.SQLiteCreateTree.AlterTable.Action;
namespace Orchard.Data.Migration.Interpreters {
public class SQLiteCommandInterpreter :
ICommandInterpreter<DropColumnCommand>,
ICommandInterpreter<AlterColumnCommand>,
ICommandInterpreter<CreateForeignKeyCommand>,
ICommandInterpreter<DropForeignKeyCommand>,
ICommandInterpreter<AddIndexCommand>,
ICommandInterpreter<DropIndexCommand> {
public class SQLiteCommandInterpreter : ICommandInterpreter<CreateTableCommand>,
ICommandInterpreter<AlterTableCommand>,
//ICommandInterpreter<CreateForeignKeyCommand>,
ICommandInterpreter<DropForeignKeyCommand> {
public string[] CreateStatements(DropColumnCommand command) {
return new string[0];
//private readonly ISession _session;
private readonly Dialect _dialect;
private readonly ShellSettings _shellSettings;
//private readonly DefaultDataMigrationInterpreter _dataMigrationInterpreter;
//public SQLiteCommandInterpreter(DefaultDataMigrationInterpreter dataMigrationInterpreter) {
// _dataMigrationInterpreter = dataMigrationInterpreter;
//}
public SQLiteCommandInterpreter(
ISessionLocator locator,
ShellSettings shellSettings,
//ITransactionManager transactionManager,
ISessionFactoryHolder sessionFactoryHolder,
IDialectService dialectService
) {
//_session = transactionManager.GetSession();
_shellSettings = shellSettings;
var configuration = sessionFactoryHolder.GetConfiguration();
_dialect = dialectService.GetDialect(configuration);
}
public string[] CreateStatements(AlterColumnCommand command) {
return new string[0];
public string DataProvider {
get { return "SQLite"; }
}
public string[] CreateStatements(CreateForeignKeyCommand command) {
return new string[0];
public string[] CreateStatements(CreateTableCommand command) {
var createTable = new CreateTableNode {
TableName = PrefixTableName(command.Name), ColumnDefinitions = command.TableCommands.OfType<CreateColumnCommand>().
Select(CreateColumnDefNode)
.ToList()
};
var visitor = new TreeStringOutputVisitor();
string[] ret = createTable.Accept(visitor).ToString().Split(new[] {System.Environment.NewLine}, StringSplitOptions.None);
return ret;
}
public string[] CreateStatements(DropForeignKeyCommand command) {
return new string[0];
}
public string[] CreateStatements(AddIndexCommand command) {
public string[] CreateStatements(AlterTableCommand command) {
return new string[0];
}
public string[] CreateStatements(DropIndexCommand command) {
return new string[0];
//private IEnumerable<string> GetIndexNodesForTable(string tableName) {
// var query = _session.CreateSQLQuery(String.Format("SELECT sql FROM sqlite_master WHERE tbl_name = '{0}' AND type = 'index'", tableName));
// var indexStrings = query.List<string>();
// return indexStrings;
//}
//private string GetCreateTableNodeFromSession(string tableName) {
// var query = _session.CreateSQLQuery(String.Format("SELECT sql FROM sqlite_master WHERE tbl_name = '{0}' AND type = 'table'", tableName));
// var createString = query.UniqueResult<string>();
// if (createString == null) {
// // we hav ea problem
// return null;
// }
// return createString;
//}
private string PrefixTableName(string tableName) {
return PrefixTableName(_shellSettings, tableName);
}
public static string PrefixTableName(ShellSettings shellSettings, string tableName)
{
if (string.IsNullOrEmpty(shellSettings.DataTablePrefix))
{
return tableName;
}
return shellSettings.DataTablePrefix + "_" + tableName;
}
public string DataProvider {
get { return "SQLite"; }
private OrchardToSQLiteAdapter CreateOrchardToSQLiteAdapter() {
return new OrchardToSQLiteAdapter(_shellSettings, _dialect);
}
private ColumnDefNode CreateColumnDefNode(CreateColumnCommand command)
{
var ret = new ColumnDefNode { ColumnName = command.ColumnName, ColumnConstraints = new List<ColumnConstraintNode>() };
//dialect converts DbType.Int16-64 to "INT" not "INTEGER" and only INTEGER columns can be autoincremented. This fixes that.
string correctType = command.IsIdentity ? "INTEGER" : _dialect.GetTypeName(new SqlType(command.DbType));
ret.TypeNameNode = SQLiteParseVisitor.ParseString<TypeNameNode>(correctType, i => i.type_name());
//not quite right but should work
if (command.IsIdentity || command.IsPrimaryKey)
{
var primKey = new PrimaryKeyConstraintNode();
if (command.IsIdentity)
{
primKey.AutoIncrement = true;
}
ret.ColumnConstraints.Add(primKey);
}
if (command.Default != null)
{
ret.ColumnConstraints.Add(new DefaultConstraintNode { Value = ConvertToSqlValue(command.Default) });
}
if (command.IsNotNull)
{
ret.ColumnConstraints.Add(new NotNullConstraintNode());
}
else if (command.Default == null && !command.IsPrimaryKey && !command.IsUnique)
{
ret.ColumnConstraints.Add(new DefaultConstraintNode { Value = "NULL" });
}
if (command.IsUnique)
{
ret.ColumnConstraints.Add(new UniqueConstraintNode());
}
return ret;
}
public string ConvertToSqlValue(object value) {
if (value == null) {
return "null";
}
TypeCode typeCode = Type.GetTypeCode(value.GetType());
switch (typeCode) {
case TypeCode.Empty:
case TypeCode.Object:
case TypeCode.DBNull:
case TypeCode.String:
case TypeCode.Char:
return String.Concat("'", Convert.ToString(value).Replace("'", "''"), "'");
case TypeCode.Boolean:
return _dialect.ToBooleanValueString((bool)value);
case TypeCode.SByte:
case TypeCode.Int16:
case TypeCode.UInt16:
case TypeCode.Int32:
case TypeCode.UInt32:
case TypeCode.Int64:
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Decimal:
return Convert.ToString(value, CultureInfo.InvariantCulture);
case TypeCode.DateTime:
return String.Concat("'", Convert.ToString(value, CultureInfo.InvariantCulture), "'");
}
return "null";
}
}
}
internal class OrchardToSQLiteAdapter {
private readonly ShellSettings _shellSettings;
private readonly Dialect _dialect;
internal OrchardToSQLiteAdapter(ShellSettings shellSettings, Dialect dialect) {
_shellSettings = shellSettings;
_dialect = dialect;
}
private OcfAction.TableCommand Visit(TableCommand command) {
if (command is AddColumnCommand) {
return Visit(command as AddColumnCommand);
}
if (command is DropColumnCommand) {
return Visit(command as DropColumnCommand);
}
if (command is AddIndexCommand) {
return Visit(command as AddIndexCommand);
}
if (command is DropIndexCommand) {
return Visit(command as DropIndexCommand);
}
if (command is AlterColumnCommand) {
return Visit(command as AlterColumnCommand);
}
return null;
}
public OcfAction.AlterTableCommand Visit(AlterTableCommand command) {
var output = new OcfAction.AlterTableCommand(PrefixTableName(command.Name));
foreach (var tc in command.TableCommands) {
output.TableCommands.Add(Visit(tc));
}
return output;
}
public OcfAction.AddColumnCommand Visit(AddColumnCommand command) {
var output = new OcfAction.AddColumnCommand(PrefixTableName(command.TableName), command.ColumnName);
output.WithType(GetTypeName(command.DbType));
if (command.IsNotNull) {
output.NotNull();
}
else {
output.Nullable();
}
if (command.IsUnique) {
output.Unique();
}
if (command.IsPrimaryKey) {
output.PrimaryKey();
}
if (command.IsIdentity) {
output.Identity();
}
output.WithDefault(command.Default);
return output;
}
public OcfAction.DropColumnCommand Visit(DropColumnCommand command) {
return new OcfAction.DropColumnCommand(PrefixTableName(command.TableName), command.ColumnName);
}
public OcfAction.AlterColumnCommand Visit(AlterColumnCommand command) {
var output = new OcfAction.AlterColumnCommand(PrefixTableName(command.TableName), command.ColumnName);
if (command.DbType != DbType.Object) {
output.WithType(GetTypeName(command.DbType));
}
output.WithDefault(command.Default);
return output;
}
public OcfAction.AddIndexCommand Visit(AddIndexCommand command) {
return new OcfAction.AddIndexCommand(PrefixTableName(command.TableName), command.IndexName, command.ColumnNames);
}
public OcfAction.DropIndexCommand Visit(DropIndexCommand command) {
return new OcfAction.DropIndexCommand(PrefixTableName(command.TableName), command.IndexName);
}
public OcfAction.AlterTableCommand Visit(DropForeignKeyCommand command) {
var output = new OcfAction.AlterTableCommand(PrefixTableName(command.SrcTable));
output.DropForeignKey(PrefixTableName(command.Name));
return output;
}
public OcfAction.AlterTableCommand Visit(CreateForeignKeyCommand command) {
var output = new OcfAction.AlterTableCommand(PrefixTableName(command.SrcTable));
output.CreateForeignKey(PrefixTableName(command.Name), command.SrcColumns, PrefixTableName(command.DestTable), command.DestColumns);
return output;
}
private string PrefixTableName(string tableName) {
return SQLiteCommandInterpreter.PrefixTableName(_shellSettings, tableName);
}
public string GetTypeName(DbType dbType) {
return _dialect.GetTypeName(new SqlType(dbType));
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Utils;
using NHibernate.Mapping;
namespace Orchard.Data.Providers
{
public class SQLiteDataServicesProvider : AbstractDataServicesProvider {
private readonly string _fileName;
private readonly string _dataFolder;
public SQLiteDataServicesProvider(string dataFolder, string connectionString) {
_dataFolder = dataFolder;
_fileName = Path.Combine(dataFolder, "Orchard.sqlite");
}
public SQLiteDataServicesProvider(string fileName) {
_dataFolder = Path.GetDirectoryName(fileName);
_fileName = fileName;
}
public static string ProviderName {
get { return "SQLite"; }
}
public override IPersistenceConfigurer GetPersistenceConfigurer(bool createDatabase) {
SQLiteConfiguration persistence = SQLiteConfiguration.Standard;
if (createDatabase) {
if (File.Exists(_fileName))
File.Delete(_fileName);
}
string localConnectionString = string.Format("Data Source='{0}'",
_fileName);
if (!File.Exists(_fileName) && !string.IsNullOrEmpty(_dataFolder)) {
Directory.CreateDirectory(_dataFolder);
}
persistence = persistence.ConnectionString(localConnectionString);
return persistence;
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Orchard.Data.Providers
{
public class SQLiteStatementProvider : ISqlStatementProvider
{
public string DataProvider
{
get { return "SQLite"; }
}
public string GetStatement(string command)
{
switch (command)
{
case "random":
return "rand()";
}
return null;
}
}
}

View File

@@ -59,6 +59,9 @@
<NoWarn>0436</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="Antlr4.Runtime.v4.0">
<HintPath>..\..\lib\antlr\Antlr4.Runtime.v4.0.dll</HintPath>
</Reference>
<Reference Include="Autofac, Version=2.1.13.813, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\autofac\Autofac.dll</HintPath>
@@ -104,6 +107,12 @@
<Reference Include="Owin">
<HintPath>..\..\lib\owin\Owin.dll</HintPath>
</Reference>
<Reference Include="Outercurve.SQLiteCreateTree">
<HintPath>..\..\lib\sqlite-createsupport\Outercurve.SQLiteCreateTree.dll</HintPath>
</Reference>
<Reference Include="Outercurve.SQLiteParser">
<HintPath>..\..\lib\sqlite-createsupport\Outercurve.SQLiteParser.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
@@ -228,12 +237,15 @@
<Compile Include="Data\DefaultSessionConfigurationEvents.cs" />
<Compile Include="Data\DoNotMapAttribute.cs" />
<Compile Include="Data\FetchRequest.cs" />
<Compile Include="Data\Migration\Interpreters\DialectService.cs" />
<Compile Include="Data\SessionConfigurationEventsWithParameters.cs" />
<Compile Include="Data\ISessionConfigurationEventsWithParameters.cs" />
<Compile Include="Data\Migration\Interpreters\MySqlCommandInterpreter.cs" />
<Compile Include="Data\Providers\MySqlStatementProvider.cs" />
<Compile Include="Data\Providers\SqlCeStatementProvider.cs" />
<Compile Include="Data\Providers\ISqlStatementProvider.cs" />
<Compile Include="Data\Providers\SQLiteDataServicesProvider.cs" />
<Compile Include="Data\Providers\SQLiteStatementProvider.cs" />
<Compile Include="Data\Providers\SqlServerStatementProvider.cs" />
<Compile Include="Data\Providers\PostgreSqlStatementProvider.cs" />
<Compile Include="Data\Providers\PostgreSqlDataServicesProvider.cs" />